我正在使用Wildfly 10.0.0 Final,Java EE7,Maven和JPA 2.1。当我查询我的数据库中的记录时,它工作正常并列出了员工,但是当我试图坚持新员工时,它给了我以下例外:
javax.servlet.ServletException: WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:671)
io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
...
我正在尝试使用JSF和CDI bean来实现它。我有一个JTA数据源,我在persistence.xml文件中配置了它:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="MyPersistenceUnit">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:/EmployeesDS</jta-data-source>
<class>com.home.entity.Employee</class>
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hbm2ddl.auto" value="update"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
</persistence>
CDI bean可以在下面看到。它相对简单,有一种方法可以列出25名员工,另一种方法可以保留特定员工:
@Named
@RequestScoped
public class DataFetchBean {
@PersistenceContext
EntityManager em;
public List getEmployees() {
Query query = em.createNamedQuery("findEmployees");
query.setMaxResults(25);
return query.getResultList();
}
public String getEmployeeNameById(final int id) {
addEmployee();
Query query = em.createNamedQuery("findEmployeeNameById");
query.setParameter("empno", id);
Employee employee = (Employee) query.getSingleResult();
return employee.getFirstName() + " " + employee.getLastName();
}
public void addEmployee() {
em.persist(new Employee(500000, new Date(335077446), "Josh", "Carribean", 'm', new Date(335077446)));
}
}
员工实体类可以在下面找到:
@NamedQueries({
@NamedQuery(
name = "findEmployees",
query = "select e from Employee e"
),
@NamedQuery(
name = "findEmployeeNameById",
query = "select e from Employee e where e.empNo = :empno"
)
})
@Table(name = "employees")
public class Employee {
@Id
@Column(name = "emp_no")
private int empNo;
@Basic
@Column(name = "birth_date")
private Date birthDate;
@Basic
@Column(name = "first_name")
private String firstName;
@Basic
@Column(name = "last_name")
private String lastName;
@Basic
@Column(name = "gender")
private char gender;
@Basic
@Column(name = "hire_date")
private Date hireDate;
public Employee() { }
public int getEmpNo() {
return empNo;
}
public void setEmpNo(int empNo) {
this.empNo = empNo;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public Date getHireDate() {
return hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
public Employee(int empNo, Date birthDate, String firstName, String lastName, char gender, Date hireDate) {
this.empNo = empNo;
this.birthDate = birthDate;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.hireDate = hireDate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
if (empNo != employee.empNo) return false;
if (gender != employee.gender) return false;
if (birthDate != null ? !birthDate.equals(employee.birthDate) : employee.birthDate != null) return false;
if (firstName != null ? !firstName.equals(employee.firstName) : employee.firstName != null) return false;
if (lastName != null ? !lastName.equals(employee.lastName) : employee.lastName != null) return false;
if (hireDate != null ? !hireDate.equals(employee.hireDate) : employee.hireDate != null) return false;
return true;
}
@Override
public int hashCode() {
int result = empNo;
result = 31 * result + (birthDate != null ? birthDate.hashCode() : 0);
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
result = 31 * result + (int) gender;
result = 31 * result + (hireDate != null ? hireDate.hashCode() : 0);
return result;
}
}
提前致谢!
答案 0 :(得分:9)
基本上存在一个容器管理的JTA感知持久化上下文与bean管理事务(BMT)。
因此,除了EntityManager
之外,您还应该在DataFetchBean
中注入UserTransaction
,以便开始,提交或回滚交易。
@Named
@RequestScoped
public class DataFetchBean {
@PersistenceContext
EntityManager em;
@Resource
private UserTransaction userTransaction;
...
}
然后,在您的addEmployee
方法中,您必须开始然后提交您的交易,以便您对员工实体的更改可以传播到数据库。
public void addEmployee() throws Exception {
Employee employee = new Employee(500000, new Date(335077446), "Josh", "Carribean", 'm', new Date(335077446));
userTransaction.beginTransaction();
em.persist(employee);
userTransaction.commit();
}
尽管如此,您应该考虑将数据库操作迁移到EJB中,将其注入到JSF bean中,因此委托容器管理事务的责任,即使用CMT,而不是手动处理它们
答案 1 :(得分:5)
另一种处理方法是在@Transactional
方法DataFetchBean
上使用注释addEmployee
。然后您不需要UserTransaction
并且可以使用AOP来管理交易。
这是JTA 1.2中添加的新功能。
答案 2 :(得分:0)
您可以在下面看到有关处理交易的文件:
Container-Managed Transactions JEE6
根据您的申请使用Transaction Attributes
答案 3 :(得分:0)
在您的方法上添加@Transactional批注,它将使其变为“ transactional”
答案 4 :(得分:0)
一种简单的方法,将@Transactional(Transactional.TxType.REQUIRED)
添加到方法
答案 5 :(得分:0)
我遇到了同样的问题,解决方法是
@Transactional(rollbackOn = Exception.class)
添加到Bean调用的方法
答案 6 :(得分:0)
与此示例不完全相关,但我遇到了另一个问题。我的项目已经在使用容器管理事务 (CMT) 并收到此错误。
我的问题是我忘记在 EJB 中包含 @Stateless 注释。添加该注解(或其他注解到类)使其实际上是容器管理的并提供所需的事务。