Tovább próbálkozom JPA-val (előző). Most szintén egy szintetikus osztályban szeretnék négyfajta Map-et tesztelni:
Map<String, String>, Map<String, OtherEntity2>, Map<OtherEntity1, String>, Map<OtherEntity1, OtherEntity2>
Az első, és meglepetésemre az utolsó kettő hibátlanul működik, azonban a második Map-et nem tudom persisztálni, azaz a String kulcshoz saját entitásosztályt rendelő Map-et.
A kód a következő:
@Entity
public class Adatlap implements Serializable {
/* ... */
@ManyToMany(fetch=FetchType.EAGER)
private Map<String, Valasz> szoveg_valasz;
/* ... */
}
Ahol a Valasz osztály egy jól működő entitásosztály.
A szindróma a következő: Hiba nélkül tudom kódból persisztálni az adott entitásosztályt, majd visszatölteni. Miután a kódban két bejegyzést hozzáadok a Map-hez, az adatbázisban a következő sorok lesznek:
mysql> SELECT *
-> FROM `ADATLAP_VALASZ`
-> LIMIT 0 , 30;
+------------+------------------+-------------------+
| Adatlap_ID | szoveg_valasz_ID | SZOVEG_VALASZ_KEY |
+------------+------------------+-------------------+
| 57 | 55 | NULL |
| 57 | 54 | NULL |
+------------+------------------+-------------------+
Azaz valamiért a SZOVEG_VALASZ_KEY (varchar típusúként hozza létre), azaz a Map String típusú kulcsa NULL-ként íródik be az adatbázisba. Igen, ez azt jelenti, hogy az adatbázisban nincs meg az érték, mégis vissza tudom tölteni az entitásmenedzserből! Miután flush-solom a Connection Poolt, azután jönnek majd a hibaüzenetek:
(Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.QueryException
Exception Description: The field [ADATLAP.SZOVEG_VALASZ_KEY] in this expression has an invalid table in this context.
Próbálkozásaim:
- Integer kulccsal ugyanez a helyzet
-
@ManyToMany(fetch=FetchType.EAGER, targetEntity=Valasz.class) @MapKeyClass(String.class)
annotációkkal ugzanez a helyzet
-
@MapKeyColumn
annotációval még az oszlopnevet is átállíthatom, az újba is NULL-t ír
-
@ElemntCOllection
annotáció nyílván nem játszik, mivel az érték saját entitás
A Java EE tutorial megfelelő bejegyzése szerint "By default, the name attribute of @MapKeyColumn is of the form RELATIONSHIP FIELD/PROPERTY NAME_KEY. For example, if the referencing relationship field name is image, the default name attribute is IMAGE_KEY.", ez meg is történik, csak épp NULL a beleírt érték.
A legidegesítőbb, hogy ha ezt a Stringet egy Entitásosztállyal wrappelem, akkor működik ugyebár (lásd Map<OtherEntity1, String>).
Kérdésem az lenne, hogy milyen annotáció/PersistenceProvider beállítás szükséges ahhoz, hogy ez az egyszerűnek hitt mapping működjön?
(GlassFish v3, Eclipse Persistence Services - 2.0.1)
- 1841 megtekintés
Hozzászólások
subscribe
- A hozzászóláshoz be kell jelentkezni
Up(1) - Nyílván egy StringWrapper entitásosztály megoldaná a problémát, de ez elég csúnya megoldás.
- A hozzászóláshoz be kell jelentkezni
Up(2) - Nincs kedvem angolul is megfogalmazni... tényleg nincs ötlet?
- A hozzászóláshoz be kell jelentkezni
Tranzakciókezelés van e?
Az Adatlap és Valasz objektumokat külön mented, vagy egyben mented az egészet? Esetleg másold be azt a részletet, ahol a mentést végzed.
Nekem ez elég fura, hogy "ADATLAP.SZOVEG_VALASZ_KEY"-ra panaszkodik, amikor az Adatlap táblán nem is kell, hogy legyen olyan oszlop.
Kipróbáltam nálam és működött szépen (igaz ez egy hibernate-s springes alkalmazás, de ez is ugyanúgy JPA 2.0):
public class AdatlapDao {
@PersistenceContext
private EntityManager em;
@Transactional
public Adatlap generateRandomAdatlap() {
Valasz valasz1 = new Valasz();
Valasz valasz2 = new Valasz();
em.persist(valasz1);
em.persist(valasz2);
Adatlap adatlap = new Adatlap();
adatlap.setValaszok(new HashMap<String, Valasz>());
adatlap.getValaszok().put("foo", valasz1);
adatlap.getValaszok().put("bar", valasz2);
em.persist(adatlap);
return adatlap;
}
}
Szépen lementette az entitásokat is meg a kapcsolataikat is (a map kulcsokat is).
- A hozzászóláshoz be kell jelentkezni
Hát igen, elég fura, főleg azért, mert olyan nincs, hogy ADATLAP.SZOVEG_VALASZ_KEY, viszont olyan lenne, hogy ADATLAP_VALASZ.SZOVEG_VALASZ_KEY ... :\
A kód, ami a perzisztálást végzi, a NetBeans által generált JPA controller class, amely sejtésem szerint tranzakciókezeléssel csinálja.
public AdatlapJpaController() {
emf = Persistence.createEntityManagerFactory("AdatlapPU");
}
private EntityManagerFactory emf = null;
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void create(Adatlap adatlap) {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
em.persist(adatlap);
em.getTransaction().commit();
} finally {
if (em != null) {
em.close();
}
}
}
Más sem nagyon szív ezzel, nekem egyre gyanúsabb, hogy az EclipseLink a bugos. De hát az a referencia implementáció, nem?
- A hozzászóláshoz be kell jelentkezni
de. ha raer holnapig, holnap megnezem, mostmar epp agybol vagyok. :)
- A hozzászóláshoz be kell jelentkezni
Azt megintcsak megköszönném.
Szerkesztve: Annyit még mindenképpen megemlítenék, hogy az ADATLAP_VALASZ.SZOVEG_VALASZ_KEY oszlop varchar(255)-ként jött létre, tehát ez a legidegesítőbb, hogy kb. oda csak be kéne írnia a kulcs szövegét. Csakhát ez a "The field [ADATLAP.SZOVEG_VALASZ_KEY] in this expression has an invalid table in this context." Üzenet...
- A hozzászóláshoz be kell jelentkezni
Fejlemény:
Az én tippem az volt, hogy EclipseLink bugos, ebben már egyre biztosabb vagyok, tekintve, hogy pár kattintás és némi kódhegesztés után a persistence providert Hibernate-re állítva minden működik az elvárt módon...
Ettől függetlenül az IDE-támogatás miatt továbbra is érdekelne az EclipseLink-es megoldás is.
- A hozzászóláshoz be kell jelentkezni
Mondjuk Hibernate esetén valamiért nem működik az em.getCriteriaBuilder() (a NetBeans a generált controller osztályában így kéri le az entitásokat). Ezt átírva működik persze, pl.: em.createQuery("SELECT OBJECT(a) FROM Adatlap a");
- A hozzászóláshoz be kell jelentkezni
Nálam az is megy Hibernate-tel:
@Transactional(readOnly = true)
public List<Adatlap> loadAdatlaps() {
CriteriaQuery<Adatlap> query = em.getCriteriaBuilder().createQuery(Adatlap.class);
query.from(Adatlap.class);
return em.createQuery(query).getResultList();
}
- A hozzászóláshoz be kell jelentkezni
Nem tudom hogy menyivel jobb/rosszabb az eclipseLinks de Hibernate-hez is van IDE támogatás :
http://jboss.org/tools/download.html
(nem kenyerem téged rábeszélni csak megjegyzés)
- A hozzászóláshoz be kell jelentkezni