Greetings ObjectDB Users!
I'm new to the product, and I've setup a simple test after reading the tutorial, and I'm running into some issues with queries, specifically querying by primary key. I have a domain object class Called Department, which has a member of type DomainId. DomainId has two member fields: String accountId and String objectId. The following code shows these two classes.
package test.Domain; ...imports.... @Entity @Access(AccessType.PROPERTY) @NamedQueries({ @NamedQuery(name="Department.findAll", query="SELECT d FROM Department AS d"), @NamedQuery(name="Department.byName", query="SELECT d from Department AS d WHERE d.name = :name"), @NamedQuery(name="Department.findByCmpPK", query="SELECT d FROM test.Domain.Department AS d " + "WHERE d.domainId.accountId = :aid AND d.domainId.objectId = :oid"), @NamedQuery(name="Department.findByPK", query="SELECT d FROM Department AS d WHERE d.domainId.equals(:id)") }) public class Department implements Serializable { public static final long serialVersionUID = 1L; private DomainId domainId; private String name; private Set<Person> employees; public Department() { super(); } public Department(DomainId domainId, String name, Set<Person> employees) { super(); this.domainId = domainId; this.name = name; this.employees = employees; } @EmbeddedId public DomainId getDomainId() { return domainId; } public void setDomainId(DomainId domainId) { this.domainId = domainId; } @Unique(name="name2") public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToMany(fetch=FetchType.LAZY) public Set<Person> getEmployees() { return employees; } public void setEmployees(Set<Person> employees) { this.employees = employees; } public boolean equals(Object obj) { if(((Department) obj).getDomainId() == null || this.domainId == null) return false; return this.domainId.equals(obj); } }
package test.Domain; ...imports.... @Embeddable @Access(AccessType.PROPERTY) public class DomainId implements Serializable { public static final long serialVersionUID = 1L; private String accountId; private String objectId; public DomainId(String accountId, String objectId) { super(); this.accountId = accountId; this.objectId = objectId; } public DomainId() { super(); } @Basic(optional=false) public String getAccountId() { return accountId; } public void setAccountId(String accountId) { this.accountId = accountId; } @Basic(optional=false) public String getObjectId() { return objectId; } public void setObjectId(String objectId) { this.objectId = objectId; } public synchronized static String getNewId(){ UUID uuid = UUID.randomUUID(); return uuid.toString().replaceAll("-",""); } public boolean equals(Object obj) { if(obj instanceof DomainId){ DomainId foreign = (DomainId) obj; if(this.accountId == null || this.objectId == null) return false; if(foreign.getAccountId() == null || foreign.getObjectId() == null) return false; return (this.accountId.equals(foreign.getAccountId())) && (this.objectId.equals(foreign.getObjectId())); } return false; } }
I then setup a JUnit test case, like this:
package test.test; ....imports..... public class TestDepartment { private EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-pu"); private EntityManager em; private DomainId departmentId; private Department foundResult = null; @Before public void setUp(){ this.em = emf.createEntityManager(); this.departmentId = new DomainId(DomainId.getNewId(), DomainId.getNewId()); } @Test public void createDepartment(){ Department department = new Department(this.departmentId, "dOne", null); try{ em.getTransaction().begin(); em.persist(department); em.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); if(em.getTransaction().isActive()) em.getTransaction().rollback(); assertTrue(false); } } @Test public void findDepartment(){ Department d = em.find(Department.class, this.departmentId); assertNotNull(d); assertNotNull(d.getDomainId()); assertEquals(this.departmentId, d.getDomainId()); } @Test public void queryDepById(){ TypedQuery<department> q = em.createNamedQuery("Department.findByPK", Department.class); q.setParameter("id", this.departmentId); Department d = q.getSingleResult(); assertNotNull(d); assertNotNull(d.getDomainId()); assertEquals(this.departmentId, d.getDomainId()); this.foundResult = d; } @Test public void queryDepByIdComponents(){ TypedQuery&lr;Department> q = em.createNamedQuery("Department.findByCmpPK", Department.class); q.setParameter("aid", this.departmentId.getAccountId()); q.setParameter("oid", this.departmentId.getObjectId()); Department d = q.getSingleResult(); assertNotNull(d); assertNotNull(d.getDomainId()); assertEquals(this.departmentId, d.getDomainId()); this.foundResult = d; } @Test public void simpleCleanUp(){ assertNotNull(this.foundResult); try{ em.getTransaction().begin(); em.remove(this.foundResult); em.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); if(em.getTransaction().isActive()) em.getTransaction().rollback(); assertTrue(false); } } @After public void tearDown(){ //Ensure cleanup happens if lookups fail. TypedQuery<Department> q = em.createNamedQuery("Department.findAll", Department.class); q.setMaxResults(1000); List<Department> departments; try{ do{ departments = q.getResultList(); em.getTransaction().begin(); for(Department d : departments) em.remove(d); em.getTransaction().commit(); }while(departments.size() > 0); }catch(Exception e){ e.printStackTrace(); if(em.getTransaction().isActive()) em.getTransaction().rollback(); } //Finish clean up. this.foundResult = null; this.departmentId = null; em.close(); this.em = null; this.emf = null; } }
The first test, createDepartment() succeeds, and I can view the Department object in the database with the ObjectDB Explorer, including it's embedded DomainId which is filled out with the random UUID strings I generated. However, the second test findDepartment fails to find any results and returns NULL, but does not throw any exception. The third and fourth tests fail, and throw the following exception:
[ObjectDB 2.0.3] Query: SELECT d FROM Department AS d WHERE d. ==> domainId <== .equals(:id) javax.persistence.PersistenceException Field 'domainId' is not found in type 'test.Domain.Department' (error 761) (position 38) at com.objectdb.jpa.JpaQuery.getSingleResult(JpaQuery.java:592) at test.test.TestDepartment.queryDepById(TestDepartment.java:58) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41) at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.junit.runners.ParentRunner.run(ParentRunner.java:220) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
This causes the final test, simpleCleanUp to fail because the Department instance is not found, and therefore the privately scoped foundDepartment remains null. Am I doing something wrong with the use of @Embedded, @EmbeddedId or with my JPQL queries or is this a bug? Any help would be greatly appreciated.