I created a data model to test many-to-many relationship with a link table as following (full code in attachement)
@Entity public class User { @Id private String code; @OneToMany(mappedBy = "user") @MapKey private Map<Assignement.PK, Assignement> assignements; } @Entity public class Project { @Id private String code; @OneToMany(mappedBy = "project") @MapKey private Map<Assignement.PK, Assignement> assignements; } @Entity @IdClass(Assignement.PK.class) public class Assignement { @Id @ManyToOne(cascade = CascadeType.ALL, optional = false) private User user; @Id @ManyToOne(cascade = CascadeType.ALL, optional = false) private Project project; @Embeddable public static class PK { public String user; public String project; public PK(User user, Project project) { this.user = user.getCode(); this.project = project.getCode(); } } }
The following test passed OK, everything is as expected
EntityManager em = EMF.get().createEntityManager(); User u1 = new User("u1"); User u2 = new User("u2"); Project p1 = new Project("p1"); Project p2 = new Project("p2"); em.getTransaction().begin(); em.persist(p1); em.persist(p2); em.persist(u1); em.persist(u2); em.persist(new Assignement(u1, p1)); em.persist(new Assignement(u1, p2)); em.persist(new Assignement(u2, p1)); em.getTransaction().commit(); assertNull(u1.getAssignements()); em.refresh(u1); ///fetch the Assignements collection of u1 assertNotNull(u1.getAssignements()); int countProjectsAssignedToU1 = u1.getAssignements().keySet().toArray().length; assertEquals(2, countProjectsAssignedToU1); //prouve that we can access the project p1 through u1.Assignements Assignement.PK a11pk = new Assignement.PK(u1, p1); Assignement a11 = u1.getAssignements().get(a11pk); assertEquals(p1, a11.getProject());
But:
Question 1: After my test, the database file is created (in attachement) but I cannot open it with ObjectDB Explorer (Message: "Cannot open file 'demo.odb' null").
Note: I'm using Windows 7 64 bits. jdk1.6.0_27. ObjectDB doctor did not find any anormalie in the file
I found the following log file:
java.lang.NullPointerException at com.objectdb.jpa.type.IdentifiableTypeImpl.initAttributes(IdentifiableTypeImpl.java:110) at com.objectdb.jpa.MetamodelImpl.obtainType(MetamodelImpl.java:290) at com.objectdb.jpa.type.ManagedTypeImpl.newAttribute(ManagedTypeImpl.java:112) at com.objectdb.jpa.type.ManagedTypeImpl.initAttributes(ManagedTypeImpl.java:91) at com.objectdb.jpa.type.IdentifiableTypeImpl.initAttributes(IdentifiableTypeImpl.java:82) at com.objectdb.jpa.MetamodelImpl.obtainType(MetamodelImpl.java:290) at com.objectdb.jpa.MetamodelImpl.prepareTypeLists(MetamodelImpl.java:228) at com.objectdb.jpa.MetamodelImpl.getManagedTypes(MetamodelImpl.java:98) at com.objectdb.o.EHL.d(EHL.java:56) at com.objectdb.o.MTI.<init>(MTI.java:39) at com.objectdb.o.SCP.h(SCP.java:126) at com.objectdb.o.MFR.j(MFR.java:235) at com.objectdb.o.MFR.j(MFR.java:233) at com.objectdb.o.MFR.j(MFR.java:233) at com.objectdb.o.MFR.j(MFR.java:233) at com.objectdb.o.MFR.i(MFR.java:218) at com.objectdb.o.EXA.o(EXA.java:194) at com.objectdb.o.EXA.n(EXA.java:186) at com.objectdb.o.CNC.g(CNC.java:117) at com.objectdb.o.EXA.<init>(EXA.java:79) at com.objectdb.Explorer$1.run(Explorer.java:53) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:641) at java.awt.EventQueue.access$000(EventQueue.java:84) at java.awt.EventQueue$1.run(EventQueue.java:602) at java.awt.EventQueue$1.run(EventQueue.java:600) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.awt.EventQueue.dispatchEvent(EventQueue.java:611) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Question 2: All test passe. Howrever, can you tell me: Is my above implementation alright for objectDB?
I'd like to implement a many-to-many relationship so that User and Project can be directly access from Assignement (not by theirs key), and we can easily get an Assignement object from User object and Underlying object (but not through theirs keys).
I'd like to work with typed object in the code whenever possible, and make key usage as transparent as possible. The implementation above response to what I want, but I don't know if it is alright in ObjectDB. Do you have any advises/suggestion?
Regards.