I've been working with ObjectDB for the past several months, and it's behaved pretty much as expected. I made a few modifications to a working set of classes today, and it's started throwing exceptions at commit time. I've stripped it down to a set of files that seem to be of trivial complexity, but it's still failing.
It involves two entities, Index and Ostrich. The thing to note is that the Index structure is recursive through maps; but that's never caused any problem for me in the past.
package failing; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Ostrich implements Serializable { @Id long id; public Ostrich() { } }
package failing; import java.io.Serializable; import java.util.Map; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.OneToOne; import static javax.persistence.CascadeType.*; import static javax.persistence.FetchType.*; @Entity public class Index implements Serializable { @Id @GeneratedValue private long id; @OneToOne(fetch=EAGER, cascade=PERSIST) public Ostrich ostrich; @ManyToMany(cascade=ALL) public Map<String, Index> entries; public Index(Ostrich ostrich, Map<String, Index> entries) { this.entries = entries; this.ostrich = ostrich; } @SuppressWarnings("unused") private Index() { } public Ostrich getOstrich() { return ostrich; } }
...and a program to try it out:
package failing; import java.util.HashMap; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import com.objectdb.Enhancer; public class ODBTest { public static void main(String[] args) { Enhancer.enhance("failing.*"); EntityManagerFactory emf = Persistence.createEntityManagerFactory("./db/db0.odb"); EntityManager em = emf.createEntityManager(); Ostrich oo = new Ostrich(); Index dd = new Index(oo, new HashMap<String, Index>()); HashMap<String, Index> dEntries = new HashMap<String, Index>(); dEntries.put("xxx", dd); Ostrich o = new Ostrich(); Index d = new Index(o, dEntries); EntityTransaction tx = em.getTransaction(); tx.begin(); em.persist(d); em.persist(dd); em.persist(o); em.persist(oo); tx.commit(); } }
I had started with the expectation that the cascading annotations would be sufficient to cause everything to be persisted (and that's worked well for me in the past), but no cigars. So, you'll note that all four of the entities (2 Index, 2 Ostrich) that the test program allocated are now explicitly persisted in the transaction---and I'm still getting an exception:
Exception in thread "main" [ObjectDB 2.2.6_03] javax.persistence.RollbackException Failed to commit transaction: Attempt to persist a reference to a non managed failing.Ostrich instance (error 613) at com.objectdb.jpa.EMImpl.commit(EMImpl.java:277) at failing.ODBTest.main(ODBTest.java:38) Caused by: javax.persistence.PersistenceException: com.objectdb.o.UserException: Attempt to persist a reference to a non managed failing.Ostrich instance at com.objectdb.o._PersistenceException.b(_PersistenceException.java:47) at com.objectdb.o.JPE.g(JPE.java:140) at com.objectdb.o.JPE.g(JPE.java:78) ... 4 more Caused by: com.objectdb.o.UserException: Attempt to persist a reference to a non managed failing.Ostrich instance at com.objectdb.o.MSG.d(MSG.java:61) at com.objectdb.o.TYW.writeElement(TYW.java:246) at failing.Index.__odbWriteContent(Index.java:1) at com.objectdb.o.MMM.af(MMM.java:1025) at com.objectdb.o.UTY.aF(UTY.java:1185) at com.objectdb.o.UTY.aE(UTY.java:1174) at com.objectdb.o.ENH.a(ENH.java:46) at com.objectdb.o.STA.T(STA.java:512) at com.objectdb.o.STM.D(STM.java:408) at com.objectdb.o.OBM.bH(OBM.java:884) at com.objectdb.jdo.PMImpl.bH(PMImpl.java:2186) at com.objectdb.o.OBM.bG(OBM.java:800) at com.objectdb.o.OBM.bE(OBM.java:715) at com.objectdb.jpa.EMImpl.commit(EMImpl.java:274) ... 1 more
Any clues as to what's going on here? This is so insanely simple, I must be missing something really basic.