当前位置: 首页 > 面试题库 >

需要事务才能执行此操作(使用事务或扩展的持久性上下文)

满伟彦
2023-03-14
问题内容

我正在使用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,以开始,提交或回滚事务。

@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.begin();
    em.persist(employee);
    userTransaction.commit();
}

尽管如此,您仍应考虑将数据库操作迁移到EJB中,然后将其注入到JSF bean中,因此将管理事务的责任委托给了容器,即使用CMT,而不是手动处理事务。



 类似资料:
  • 我正在使用Wildfly 10.0。0最终版本、JavaEE7、Maven和JPA2.1。当我查询数据库中的记录时,它可以正常工作并列出员工,但当我尝试保留新员工时,它会给我以下异常: 我正在尝试使用JSF和CDI bean实现这一点。我有一个JTA数据源,我在persistence.xml文件中配置了它: CDI豆可以在下面看到。这是相对简单的,有一个方法列出25名员工和另一个应该坚持一个特定的

  • 我正在尝试使用嵌入式野蝇运行我们的JPA单元测试。到目前为止,当我进行清洁时,我得到了以下步骤的工作 嵌入式wildfly将部署在项目的/target文件夹中 MSSQL数据库驱动程序将被部署并注册为驱动程序 arquillian创建一个包含所有必需依赖项的.war文件 arquillian将我的项目的.war部署到嵌入式wildfly,并在嵌入式wildfry上开始单元测试 现在我的问题是:当我

  • 问题内容: 事务范围的持久性上下文和扩展的持久性上下文之间有什么区别? 问题答案: 在JSR-220 Enterprise JavaBeans 3.0规范中清楚地解释了差异: 5.6容器管理的持久性上下文 (…) 可以将容器管理的持久性上下文定义为具有范围为单个事务的生存期或跨越多个事务的扩展生存期,这取决于创建容器时所指定的生存期 。该规范分别将这种持久性上下文称为 事务范围的持久性上下文 和

  • 问题内容: 为什么在Hibernate中需要事务才能进行只读操作? 以下事务是否在数据库中设置了锁定? 从数据库获取示例代码: 我可以 代替使用吗? 问题答案: 您实际上可能有理由将事务标记为只读。 阅读交易看起来确实很奇怪,在这种情况下,人们通常不会标记交易方法。但是JDBC仍然会创建事务,只是如果未显式设置其他选项,它将可以正常工作。 但是,不能保证您的方法不会写入数据库。如果将method标

  • 问题内容: 为什么在Hibernate中需要事务处理才能进行只读操作? 以下事务是否在数据库中设置了锁定? 从数据库获取示例代码: 我可以 代替使用吗? 问题答案: 你实际上可能有理由将事务标记为只读。 阅读交易看起来确实很奇怪,在这种情况下,人们通常不会标记交易方法。但是JDBC仍然会创建事务,只是如果未明确设置其他选项,它将可以正常工作。 但是,不能保证你的方法不会写入数据库。如果将metho

  • 我们使用HiberNate作为JPA提供程序。当其中一个实体更新时,我需要对Quartz计划执行一些更新。目前,该代码是在该实体的更新方法中调用的。但是,Quartz更改只有在事务成功提交时才会生效。 我考虑过实现一个实体监听器,但是我只想在实体被特定方法修改时执行这些更新,并且我不确定JPA实体监听器是否支持依赖注入,我需要依赖注入来获取对Quartz调度器的引用。 有没有办法以编程方式附加活动