我正在使用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; } }
提前致谢!
基本上,一种情况是存在带有Bean管理事务(BMT)的容器管理的JTA感知持久性上下文。
因此,除了你的EntityManager你也应该注入,到你DataFetchBean,你UserTransaction,以开始,提交或回滚事务。
EntityManager
DataFetchBean
UserTransaction
@Named @RequestScoped public class DataFetchBean { @PersistenceContext EntityManager em; @Resource private UserTransaction userTransaction; ... }
然后,在您的addEmployee方法中,您必须开始然后提交事务,以便对员工实体所做的更改可以传播到数据库。
addEmployee
public void addEmployee() throws Exception { Employee employee = new Employee(500000, new Date(335077446), "Josh", "Carribean", 'm', new Date(335077446)); userTransaction.begin(); em.persist(employee); userTransaction.commit(); }
尽管如此,您仍应考虑将数据库操作迁移到EJB中,然后将其注入到JSF bean中,因此将管理事务的责任委托给了容器,即使用CMT,而不是手动处理事务。