Проблемы при внедрении менеджера сущностей в компонент без сохранения состояния - PullRequest
1 голос
/ 17 декабря 2011

Я занимаюсь разработкой EJB3-приложения, в котором я использую bean-компоненты без сохранения состояния.Похоже, что EntityManager неправильно введен в мой компонент.

Вот код для компонента без состояния:

@Stateless
@LocalBean
public class FirmEJB {

    @PersistenceContext(unitName = "Fr14_07_Nezdolij_lab3PU")
    private EntityManager em;

    @PersistenceUnit(unitName="Fr14_07_Nezdolij_lab3PU")
    private EntityManagerFactory emf;

    public FirmEJB() {
        emf = Persistence.createEntityManagerFactory("Fr14_07_Nezdolij_lab3PU");
        em = emf.createEntityManager();
    }

    public EntityManager getEm() {
        return em;
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }

    public Employee createEmployee(Employee e){
        em.persist(e);
        return e;
    }

    public Project createProject(Project p){
        em.persist(p);
        return p;
    }

    public Customer createProject(Customer c){
        em.persist(c);
        return c;
    }

    public Department createProject(Department d){
        em.persist(d);
        return d;
    }

    public ProjectManager createProjectManager(ProjectManager prjman){
        em.persist(prjman);
        return prjman;
    }

}

Когда я пытаюсь создать экземпляр FirmEJB I getследующее исключение:

Exception in thread "main" java.lang.NullPointerException
    at sttls.FirmEJB.createEmployee(FirmEJB.java:42)
    at entity.Main.main(Main.java:33)

persistence.xml :

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="Fr14_07_Nezdolij_lab3PU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/fir</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables"/>
            <property name="eclipselink.jdbc.url" value="jdbc:derby://localhost:1527/firmDB;create=true"/>
            <property name="eclipselink.jdbc.user" value="admin"/>
            <property name="eclipselink.jdbc.password" value="admin"/>
        </properties>
    </persistence-unit>
</persistence>

Код клиента :

public static void main(String[] args) throws ClassNotFoundException, Exception {

    Employee emp1 = new Employee("Alan", "Smith");

    FirmEJB firmejb = new FirmEJB();
    firmejb.createEmployee(emp1);
}

Ответы [ 2 ]

2 голосов
/ 17 декабря 2011

Вы используете функции Java EE в среде Java SE. Это не сработает.

Контейнер Java EE отвечает за внедрение зависимостей, поэтому PersisteneContext и PersistenceUnit имеют смысл только в среде контейнера Java EE (например, Glassfish или JBoss).

Если вы определите что-то вроде этого:

@PersistenceContext(unitName = "Fr14_07_Nezdolij_lab3PU")
private EntityManager em;

@PersistenceUnit(unitName="Fr14_07_Nezdolij_lab3PU")
private EntityManagerFactory emf;

public FirmEJB() {
    emf = Persistence.createEntityManagerFactory("Fr14_07_Nezdolij_lab3PU");
    em = emf.createEntityManager();
}

вы определяете внедрение зависимостей с помощью аннотаций и в то же время вы сами создаете экземпляры EMF и EM. Аннотации бессмысленны в вашем случае.

Более того:

  • в persistence.xml вы определяете для использования тип транзакции RESOURCE_LOCAL и в то же время вы определяете элемент <jta-data-source> (что означает, что вы будете использовать транзакции JTA),
  • Я предполагаю, что вы используете EclipseLink, поэтому <exclude-unlisted-classes>false</exclude-unlisted-classes> работает. Помните, что это не переносимое решение - чтобы быть уверенным, что в среде Java SE ваши сущности будут видны провайдеру JPA, вы должны определить их, используя элемент <class>.

И, наконец, что не менее важно, если вы выполняете свой код в среде Java SE, как это, и не запускаете какой-либо контейнер Embedded EJB, тогда @Stateless не требуется, потому что ваш класс не имеет никакого EJB природа . POJO, аннотированный как @Stateless или @Stateful, получает природу EJB, будучи выполненным в контейнере EJB. В этом случае он действует как обычный класс Java.

Остерегайтесь - даже если бы вы использовали контейнер Embedded EJB, код, который вы показали, будет , а не , для создания экземпляра EJB. Вы не можете использовать new FirmEJB() с EJB. Контейнер должен отвечать за предоставление вам экземпляра EJB.
В этом весь смысл абстракции - вы зависите от абстракции, а не от творчества.

Вас может заинтересовать дальнейшее чтение, например OpenJPA JPA Concepts или Документация OpenEJB .

0 голосов
/ 25 января 2016

Вам нужно изменить transaction-type="RESOURCE_LOCAL" to transaction-type="JTA"

...