执行此操作需要事务(使用事务或扩展持久性上下文) [英] Transaction is required to perform this operation (either use a transaction or extended persistence context)

查看:449
本文介绍了执行此操作需要事务(使用事务或扩展持久性上下文)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Wildfly 10.0.0 Final,Java EE7,Maven和JPA 2.1。当我查询数据库中的记录时,它工作正常,列出了员工,但当我试图坚持一名新员工时,它给了我以下例外:



<$ p $ ($使用事务或扩展持久化上下文)
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.secur ity.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
...



I'试图使用JSF和CDI bean来实现这一点。我有一个JTA数据源,我在我的persistence.xml文件中配置了这个数据源:

 <?xml version = 1.0encoding =UTF-8?> 
< persistence xmlns =http://xmlns.jcp.org/xml/ns/persistenceversion =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>
<属性>
< property name =hibernate.archive.autodetectionvalue =class/>
< property name =hibernate.show_sqlvalue =true/>
< property name =hibernate.format_sqlvalue =true/>
< property name =hbm2ddl.autovalue =update/>
< property name =hibernate.dialectvalue =org.hibernate.dialect.MySQLDialect/>
< / properties>
< / persistence-unit>
< /余辉>

CDI bean可以在下面看到。这是相对简单的,有一种方法列出25名雇员和另一名应该坚持特定雇员的方法:

  @Named 
@RequestScoped
公共类DataFetchBean {
@PersistenceContext
EntityManager em;
$ b $ public List getEmployees(){
Query query = em.createNamedQuery(findEmployees);
query.setMaxResults(25);
返回query.getResultList();
}

public String getEmployeeNameById(final int id){
addEmployee();

查询查询= em.createNamedQuery(findEmployeeNameById);
query.setParameter(empno,id);
Employee employee =(Employee)query.getSingleResult();
return employee.getFirstName()++ employee.getLastName();

$ b public void addEmployee(){
em.persist(new Employee(500000,new Date(335077446),Josh,Carribean,'m',新日期(335077446)));


$ / code $ / pre

雇员实体类可以在下面找到: (
@ b

  @NamedQueries(
@NamedQuery(
name =findEmployees,
query =从雇员e中选择e
),
@NamedQuery(
name =findEmployeeNameById,
query =从雇员e中选择e e.empNo =:empno


@Table(name =employees)
public class Employee {
@Id
@Column(name =emp_no)
private int empNo;
@Basic
@Column(name =birth_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)
私人日期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;

$ b $ 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;

雇员雇员=(雇员)o;

if(empNo!= employee.empNo)返回false;
if(gender!= employee.gender)返回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;

返回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);
返回结果;


$ / code $ / pre

预先致谢!

解决方案

基本上,一个存在于托管JTA的持久性上下文与bean管理事务(BMT)的容器管理存在。



因此,除了 EntityManager 之外,您还应该在 DataFetchBean 中注入您的 UserTransaction ,以便开始,提交或回滚事务。

  @Named 
@RequestScoped
public class DataFetchBean {
@PersistenceContext
EntityManager em;

@Resource
private UserTransaction userTransaction;
$ b $ ...
}

然后, code> addEmployee 方法,您必须先开始然后提交您的交易,以便您对员工实体的更改可以传播到数据库中。

  public void addEmployee()throws Exception {
Employee employee = new Employee(500000,new Date(335077446),Josh,Carribean,'m ',新日期(335077446));

userTransaction.beginTransaction();
em.persist(employee);
userTransaction.commit();
}

尽管如此,您应该考虑将数据库操作迁移到EJB中,将它注入到JSF bean中,因此委托容器管理事务,即使用CMT,而不是手动处理它们。


I'm using Wildfly 10.0.0 Final, Java EE7, Maven and JPA 2.1. When I am querying my database for records it works fine and lists out the employees, but when I am trying to persist a new employee it gives me the following exception:

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)
...

I'm trying to implement this using JSF and CDI beans. I have a JTA data source, which I've configured in my persistence.xml file:

<?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>

The CDI bean can be seen below. It is relatively simple, there is a method to list out 25 employees and another which should persist a specific employee:

@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)));
    }
}

The employee entity class can be found below:

@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;
    }
}

Thanks in advance!

解决方案

Basically one is in the presence of a container managed JTA aware persistence context with bean managed transactions (BMT).

Therefore, besides your EntityManager you should also inject, into your DataFetchBean, your UserTransaction, in order to begin, commit or rollback a transaction.

@Named
@RequestScoped
public class DataFetchBean {
    @PersistenceContext
    EntityManager em;

    @Resource
    private UserTransaction userTransaction;

    ...
}

Then, in your addEmployee method, you've to begin and then commit your transaction, so your changes to your employee entity can be propagated to the database.

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();
}

In spite of this, you should think about migrating the database actions into an EJB, injecting it into your JSF bean, therefore delegating on the container the onus of managing the transactions, i.e. make use of CMT, instead of manually handling them.

这篇关于执行此操作需要事务(使用事务或扩展持久性上下文)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆