EntityManager yang Disuntikkan Tidak Mengenal Entitas

Saya memiliki aplikasi Java EE yang sangat mendasar yang ditentukan di Eclipse (satu EJB, satu halaman web dengan PrimeFaces, satu entitas JPA). Ini memiliki empat proyek, satu untuk EAR, satu untuk EJB, satu untuk JPA dan satu untuk komponen web. Masalahnya adalah saya telah mencoba mengkonfigurasi Hibernate sebagai kerangka persistensi di persistence.xml di proyek JPA, dan itu tidak sepenuhnya berfungsi seperti yang saya harapkan. Di EJB saya (@Stateless) saya dapat mengambil EntityManager dengan dua cara. Saya dapat mengambilnya melalui Persistence.createEntityManagerFactory() ... entitasManagerFactory.createEntityManager(), dan saya dapat mengambilnya melalui anotasi @PersistenceContext(unitName = "") . Namun, hanya dengan yang pertama kelas Entitas saya (dijelaskan dengan @Entity) dikenali ketika saya melakukan kueri.

Kode ini berfungsi, entitas "Negara" diketahui oleh EntityManager (Hibernate) yang saya dapatkan:

final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("<unit-name>");
final EntityManager entityManager = entityManagerFactory.createEntityManager();
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Country> criteriaQuery = criteriaBuilder.createQuery(Country.class);
final Root<Country> root = criteriaQuery.from(Country.class);

tetapi menggunakan anotasi di kelas yang sama ini tidak berhasil (pengecualian diberikan, lihat di bawah):

@PersistenceContext(unitName = "<unit-name>")
private EntityManager entityManager;
...
final CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<Country> criteriaQuery = criteriaBuilder.createQuery(Country.class);
final Root<Country> root = criteriaQuery.from(Country.class);

Pada baris terakhir, pengecualian diberikan bahwa kelas "Negara" bukan "Entitas". Setelah memeriksa EntityManager yang disuntikkan, saya dapat melihat Negara dalam sesi dan konteks persistensi, namun sepertinya negara tersebut tidak mengetahuinya. Inilah pengecualian yang dilempar:

2014-10-06T16:06:29.634+0200|Severe: java.lang.IllegalArgumentException: Not an entity: class <package>.entity.Country
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
at org.hibernate.jpa.criteria.QueryStructure.from(QueryStructure.java:139)
at org.hibernate.jpa.criteria.CriteriaQueryImpl.from(CriteriaQueryImpl.java:173)
at <package>.CountrySessionBean.getCountries(CountrySessionBean.java:35)
...

Saya telah memasukkan toples Hibernate ke dalam file EAR sebagai "perpustakaan yang dibundel", dan saya juga mencoba menambahkannya ke folder "lib" di Glassfish. Karena Hibernate bekerja dengan implementasi pertama di atas, saya berasumsi Hibernate dikonfigurasi dengan benar dengan toples yang benar.

Persistensi.xml saya terlihat seperti ini (dan berada dalam proyek JPA di bawah META-INF, dan pada gilirannya merupakan bagian dari EAR):

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="<unit-name>" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

    <jta-data-source>MySQLResource</jta-data-source> <!-- DEFINED IN GLASSFISH -->

    <properties>
        <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup" /> <!-- NEEDED? -->
        <property name="hibernate.transaction.jta.platform"
            value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />

        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />

        ...
    </properties>
</persistence-unit>
</persistence>

Untuk referensi: Hibernate v4.3.6, EJB v3.2, Glassfish v4.1, JPA v2.1.

Adakah yang bisa memberi saya petunjuk apa yang saya lewatkan? Apakah diperlukan konfigurasi tambahan? Bagaimana cara memberi tahu aplikasi di mana entitas Negara berada?

Saya pikir menambahkan @Entity ke entitas akan membuatnya terdaftar (ini dilakukan ketika saya memanggil Persistence.createEntityManagerFactory(...), namun, tidak ketika EntityManager atau EntityManagerFactory disuntikkan melalui Java EE/Glassfish. Saya juga mencoba menambahkan kelas dengan ... ke persistence.xml tidak berhasil. Ketika saya memeriksa EntityManager yang disuntikkan, saya dapat menemukan kelas Negara dalam konteks persistensinya, sehingga TELAH terdaftar di dalamnya, namun saya tidak dapat menggunakan kelas tersebut dalam kueri .


person Raoul    schedule 06.10.2014    source sumber
comment
Jika saya memasukkan EntityManagerFactory melalui anotasi PersistenceUnit(unit-name=‹unit-name›) saya mendapatkan implementasi Hibernate, tetapi implementasi ini sepertinya tidak mengetahui tentang entitas Negara saya. Bagaimana bisa ada dua implementasi Hibernate, yang satu TIDAK mengetahui entitasnya, dan satu lagi TIDAK mengetahui entitasnya??? Agaknya anotasi PersistenceContext memberi Anda implementasi persistensi Glassfish, sedangkan menggunakan PersistenceUnit Anda mendapatkan implementasi persistensi aplikasi Anda sendiri, atau setidaknya saya rasa saya membacanya di suatu tempat...   -  person Raoul    schedule 06.10.2014
comment
Dengan EntityManager apa pun, disuntikkan atau tidak, ini TIDAK berhasil. Jadi sepertinya injeksi berfungsi, dan objek dikenali dan tersedia untuk Hibernate. Tetapi untuk EntityManagers yang disuntikkan sepertinya tidak tersedia menggunakan nama kelas, atau setidaknya seperti itulah sekarang... final Query query = this.entityManager.createQuery(SELECT c FROM Country c); Daftar akhir resultList = query.getResultList();   -  person Raoul    schedule 06.10.2014
comment
Masalah berlanjut di sini: link   -  person Raoul    schedule 08.10.2014


Jawaban (1)


Oke, jadi sepertinya masalahnya ada hubungannya dengan fakta bahwa saya memiliki dua instance kelas Entitas. Ini menjelaskan mengapa saya bisa melakukan kueri menggunakan bahasa kueri, tetapi tidak menggunakan kelas Entitas itu sendiri. Saya telah menelusuri kode ke MetamodelImpl yang terlihat di peta entitas, tetapi karena kelas yang didaftarkannya (dengan benar) tidak sama dengan yang digunakan di kriteriaQuery.from(). Saya telah mencari beberapa contoh kelas di folder tempat aplikasi Java EE diterapkan, tetapi saya belum menemukan banyak contoh kelas itu sendiri. Jadi mungkin ini ada hubungannya dengan pemuatan kelas dan/atau fakta bahwa aplikasi tersebut berisi beberapa sub-proyek (jpa, web, ejb) yang masing-masing merujuk pada kelas Entitas, atau mungkin karena Eclipse baik dalam cara penerapannya atau cara pembuatannya yang terpisah. bagian...

Bagaimanapun, masalahnya tampaknya bukan pada JPA, Hibernate, EJB, dll.

person Raoul    schedule 07.10.2014