I wanted to persist an object(ReportBean
) to the database, but I got error message:
javax.persistence.TransactionRequiredException: Transaction is required to perform this operation (either use a transaction or extended persistence context)
Here is a bit of a code:
entity
@Entity
@Table(name="t_report")
@Access(AccessType.FIELD)
public class ReportBean implements Serializable {
// fields (@Column, etc.)
// setters/getters methods
// toString , hashCode, equals methods
}
custom annotation for allowing EntityManager injection (with @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 provider
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 class - has a method to persist report to the database.
I am trying to stick with the most important imports.
If I want to use the EntityManager
to create a query (or NamedQuery as in the example) everything works.
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
: Here in the createReport()
method when the em.persist executes is where the error appear. I thought that the transaction is managed by the container (CMT
), but now I think I am wrong. Where have I made a mistake? What is the right way to implement CMT?
Here is also my 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>
Please let me know if something in my question is not clear.
See Question&Answers more detail:
os