Comment mettre en œuvre gérée par le conteneur de transaction (CMT)?

J'ai voulu persister un objet(ReportBean) à la base de données, mais j'ai eu le message d'erreur:

javax.persistence.TransactionRequiredException: Transaction is required to perform this operation (either use a transaction or extended persistence context)  

Voici un peu de code:

entité

@Entity
@Table(name="t_report")
@Access(AccessType.FIELD)
public class ReportBean implements Serializable {

    //fields (@Column, etc.)
    //setters/getters methods
    //toString , hashCode, equals methods
}

annotations personnalisées pour permettre à l'EntityManager injection (avec @Inject)

import javax.inject.Qualifier;
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Target;

@Qualifier
@Target({TYPE, METHOD, FIELD, PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyEm {
}

EntityManager fournisseur de

import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;

public class EntityManagerProvider {

    private final String PERSISTENCE_UNIT = "MyPersistenceUnit";

    @SuppressWarnings("unused")
    @Produces
    @MyEm 
    @PersistenceContext(unitName=PERSISTENCE_UNIT, type=PersistenceContextType.TRANSACTION)
    private EntityManager em;

}

ValidateReportAction classe - a une méthode pour persister rapport à la base de données.

Je suis en train de coller avec les importations les plus importantes.

Si je veux utiliser le EntityManager pour créer une requête (ou NamedQuery comme dans l'exemple) tout fonctionne.

import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.enterprise.context.SessionScoped;


@Named("validateReportAction")
@SessionScoped
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ValidateReportAction extends ReportAction implements Serializable {

    private static final long serialVersionUID = -2456544897212149335L;

    @Inject @MyEm
    private EntityManager em;

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public synchronized String createReport() {
        ReportBean report = new Report();
        //set report properties
        //em.createNamedQuery("queryName").getResultList(); ---- works
        em.persist(report)
    }
}

Q: Ici, dans la createReport() méthode lorsque l'em.persistent s'exécute est où l'erreur apparaît. Je pensais que la transaction est gérée par le conteneur (CMT), mais maintenant je pense que je me trompe. Où ai-je fait une erreur? Quelle est la bonne façon de mettre en œuvre CMT?

Ici est aussi mon persistence.xml configuration:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="MyPersistenceUnit" transaction-type="JTA">

        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/TimeReportDS</jta-data-source>
        <mapping-file>META-INF/orm.xml</mapping-file> 

        <class>....</class>
        <class>....</class>
        <class>....</class>

        <properties>

            <property name="jboss.entity.manager.factory.jndi.name"
                value="java:/modelEntityManagerFactory" />

            <!-- PostgreSQL Configuration File -->
            <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
            <property name="hibernate.connection.password" value="password" />
            <property name="hibernate.connection.url" value="jdbc:postgresql://192.168.2.125:5432/t_report" />
            <property name="hibernate.connection.username" value="username" />

            <!-- Specifying DB Driver, providing hibernate cfg lookup
                 and providing transaction manager configuration -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class"
                value="org.hibernate.transaction.JBossTransactionManagerLookup" />
            <property name="hibernate.archive.autodetection" value="class" />

            <!-- Useful configuration during development - developer can see structured SQL queries -->
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="false" />

        </properties>
    </persistence-unit>
</persistence> 

S'il vous plaît laissez-moi savoir si quelque chose dans ma question n'est pas claire.

OriginalL'auteur nyxz | 2012-01-07