JPA - Children nicht aktuell

Hi!

Ich habe eine Entity [Material] mit Relation zur Entity [Lieferant] (1:n). Diese hole ich mir so:

        
        try {
            DB db = new DB();
            em = db.getEntityManager();

            em.getTransaction().begin();
            material = em.find(Material.class, id);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }

       List<Lieferant> ll = material.getLieferantList();

Wenn ich davor neue Lieferanten mit JPA funktionen hinzufüge, dann heißt es in Zeile 16, dass die LieferantList leer ist. In der Datenbank sind Einträge für Lieferanten vorhanden.

Wenn ich umgekehrt Lieferanten entferne, dann sind diese in der LieferantList weiterhin vorhanden.

Erst nach einem Neustart der App sind die Lieferanten so aktuell, wie in der Datenbank.

Wo liegt wohl das Problem?

Danke

Daniel

ist DB eine Klasse die man kennen muss? wie wird intern der EntityManager erzeugt, oder gar ein bestehender verwendet,
oder injiziert so dass unbekannt ist, wann erzeugt?

wie lange läuft die ‘App’ schon vorher, also was ist das andere Einfügen ‘mit JPA’,
passiert das im selben Programmablauf, benutzt das ein eigenes DB-Objekt?


besteht die Möglichkeit dass da doch schon länger eine Session/ Transaktion läuft?
du kannst ja zumindest in Zeile 6 abfragen ob dort die Transaktion von em schon aktiv ist, das wäre ein Anzeichen,

aber beginTransaction() würde dann auch Exception werfen wie ich gerade sehe? also keine Transaktion aktiv

bringt ein clear() auf em in Zeile 6 etwas? ich glaube es kann auch ohne laufende Transaktion noch alter Stand gecacht werden…,
woher der aber kommt?..

in meinem Programm mit Hibernate und Session habe ich standardmäßig ein clear() dabei am Ende bestimmter größerer Abschnitte,
ob ohne Transaktion, oder commit() wie auch rollback()

Ja die liebe DB Klasse. In der wird der EM so erzeugt:

    private  EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
    
    public  synchronized EntityManager getEntityManager(){
        return emf.createEntityManager();
    }
}```

Für jede Transaktion klasse ich mir einen neuen EM geben. Nichteinmal find() oder select lasse ich ohne eine Transaktion laufen, weil es da schon üble Überraschungen gab. Im FinallyBlock wird der EM immer closed.

Wie lange die App läuft: Nach dem Start entferne ich z.B. Lieferanten. 
```EntityManager em = null;
        
        try {
            DB db = new DB();
            em = db.getEntityManager();

            em.getTransaction().begin();
            lieferant = em.merge(lieferant);
            em.remove(lieferant);
            em.getTransaction().commit();

            material.getLieferantList().remove(lieferant);
            
        } finally {
            if (em != null) {
                em.close();
            }
        }```
Nach einem em.find() stehen diese noch in der List, obwohl alle EM dieselbe EMF liefert und die EMF es mitbekommen haben sollte, dass die Lieferanten gelöscht wurden.

Ein clear() bringt hier nichts. Nur wenn ich den Cache mit ```em.getEntityManagerFactory().getCache().evict(Material.class);``` aufräumen lasse, dann funktioniert es, aber dann stellt sich die Frage nach dem Sinn eines Caches.

Zeile 12 material.getLieferantList().remove(lieferant); außerhalb der Transaktion ist ja etwas verdächtig,
was passiert wenn du das vor Zeile 10 machst?

dass man das überhaupt ggfs. selber zusätzlich machen muss ist glaube ich ein bekanntes Feature…

[QUOTE=SlaterB]Zeile 12 material.getLieferantList().remove(lieferant); außerhalb der Transaktion ist ja etwas verdächtig,
was passiert wenn du das vor Zeile 10 machst?

dass man das überhaupt ggfs. selber zusätzlich machen muss ist glaube ich ein bekanntes Feature…[/QUOTE]
Wenn ich die Zeile 12 in die Transaktion packe, dann gibt es eine Exception. Dagegen wird der Lieferant entfernt, wenn ich die Beziehung zwischen Material und Lieferant mit orphanRemoval=true parametriere, aber solange ich die Caches nicht in den Griff bekomme verzichte ich sicherheitshalber darauf.