web-dev-qa-db-de.com

Für diesen Vorgang ist eine Transaktion erforderlich (verwenden Sie entweder eine Transaktion oder einen erweiterten Persistenzkontext).

Ich verwende Wildfly 10.0.0 Final, Java EE7, Maven und JPA 2.1. Wenn ich meine Datenbank nach Datensätzen abfrage, funktioniert es einwandfrei und listet die Mitarbeiter auf. Wenn ich jedoch versuche, einen neuen Mitarbeiter beizubehalten, gibt es die folgende Ausnahme:

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

Ich versuche dies mit JSF und CDI-Beans zu implementieren. Ich habe eine JTA-Datenquelle, die ich in meiner Datei persistence.xml konfiguriert habe:

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

Die CDI-Bean ist unten zu sehen. Es ist relativ einfach, es gibt eine Methode, um 25 Mitarbeiter aufzulisten, und eine andere, die einen bestimmten Mitarbeiter beibehalten soll:

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

Die Mitarbeiter-Entitätsklasse finden Sie unten:

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

Danke im Voraus!

5
masm64

Grundsätzlich ist ein Container-verwalteter JTA-fähiger Persistenzkontext mit Bean-verwalteten Transaktionen (BMT) vorhanden.

Daher sollten Sie neben Ihrer EntityManager auch Ihre DataFetchBean in Ihre UserTransaction einfügen, um eine Transaktion zu starten, festzuschreiben oder zurückzusetzen.

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

    @Resource
    private UserTransaction userTransaction;

    ...
}

Anschließend müssen Sie in Ihrer addEmployee -Methode Ihre Transaktion starten und anschließend festschreiben, damit Ihre Änderungen an Ihrer Mitarbeiterentität in die Datenbank übernommen werden können.

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

Trotzdem sollten Sie überlegen, die Datenbankaktionen in eine EJB zu migrieren, sie in Ihre JSF-Bean zu injizieren und somit die Verantwortung für die Verwaltung der Transaktionen, d. H. Die Verwendung von CMT, auf den Container zu delegieren, anstatt sie manuell zu verarbeiten.

9
aribeiro

Eine alternative Möglichkeit, dies zu handhaben, besteht darin, die Annotation @Transactional für die Methode DataFetchBean Ihrer addEmployee zu verwenden. Dann brauchen Sie die UserTransaction nicht und können die Transaktion mit AOP verwalten.

Dies war eine neue Funktion in JTA 1.2.

5
John Ament

[.________.] Container-verwaltete Transaktionen JEE6

use Transaction Attributes based on your application

0
Alireza Alallah

füge @Transactional Annotation zu deiner Methode hinzu, um sie "transaktional" zu machen.

0
cyril