Hello,
we try to change the class hierarchy of an Entity.
You wrote www.objectdb.com/database/forum/899 that ObjectDB support automatic schema evolution for adding and removing fields and for class hierarchy change.
But our small test failed:
At first create a DataBase with one Object of MyEntity
package profileMigration.classhierachychange; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public final class Test { public static void main(String[] args) { System.out.println("start"); EntityManagerFactory emf = Persistence .createEntityManagerFactory("objectdb:$objectdb/db/test.tmp;drop"); EntityManager em = emf.createEntityManager(); // Persist an entity em.getTransaction().begin(); MyEntity entity = new MyEntity(); entity.id = "123"; entity.name = "name123"; entity.value = "value123"; em.persist(entity); em.getTransaction().commit(); em.getTransaction().begin(); MyEntity entityWithID1 = em.find(MyEntity.class, 1); System.out.println(entityWithID1.id); System.out.println(entityWithID1.name); System.out.println(entityWithID1.value); em.getTransaction().commit(); em.close(); emf.close(); } @Entity public static class BaseEntity { @Basic String id; } @Entity public static class NamedEntity extends BaseEntity { @Basic String name; } @Entity public static class MyEntity extends NamedEntity { // @Basic // String name; @Basic String value; } }
Then we change the class hierarchy of MyEntity from NamedEntity to BaseEntity:
[Please note the changes in the Main method]
package profileMigration.classhierachychange; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public final class Test { public static void main(String[] args) { System.out.println("start"); EntityManagerFactory emf = Persistence .createEntityManagerFactory("objectdb:$objectdb/db/test.tmp"); //no drop - reuse the existing file EntityManager em = emf.createEntityManager(); //don't create a new object! // // Persist an entity // em.getTransaction().begin(); // MyEntity entity = new MyEntity(); // entity.id = "123"; // entity.name = "name123"; // entity.value = "value123"; // em.persist(entity); // em.getTransaction().commit(); em.getTransaction().begin(); MyEntity entityWithID1 = em.find(MyEntity.class, 1); System.out.println(entityWithID1.id); //System.out.println(entityWithID1.name); System.out.println(entityWithID1.value); em.getTransaction().commit(); em.close(); emf.close(); } @Entity public static class BaseEntity { @Basic String id; } @Entity public static class NamedEntity extends BaseEntity { @Basic String name; } @Entity public static class MyEntity extends BaseEntity { // @Basic // String name; @Basic String value; } }
I get the following exception:
Exception in thread "main" [ObjectDB 2.6.2_06] javax.persistence.PersistenceException Failed to read the value of field field profileMigration.classhierachychange.Test$NamedEntity.name using reflection (error 363) at com.objectdb.jpa.EMImpl.find(EMImpl.java:630) at com.objectdb.jpa.EMImpl.find(EMImpl.java:545) at profileMigration.classhierachychange.Test.main(Test.java:29) Caused by: com.objectdb.o.UserException: Failed to read the value of field field profileMigration.classhierachychange.Test$NamedEntity.name using reflection at com.objectdb.o.MSG.d(MSG.java:75) at com.objectdb.o.UMR.P(UMR.java:934) at com.objectdb.o.UMR.B(UMR.java:609) at com.objectdb.o.UML.v(UML.java:549) at com.objectdb.o.MMM.ah(MMM.java:1103) at com.objectdb.o.UTY.aG(UTY.java:1331) at com.objectdb.o.UTY.aF(UTY.java:1303) at com.objectdb.o.ENH.b(ENH.java:102) at com.objectdb.o.LDR.J(LDR.java:800) at com.objectdb.o.LDR.U1(LDR.java:1031) at com.objectdb.o.MST.aX(MST.java:544) at com.objectdb.o.MST.aW(MST.java:471) at com.objectdb.o.MST.U8(MST.java:442) at com.objectdb.o.WRA.U8(WRA.java:266) at com.objectdb.o.LDR.F(LDR.java:536) at com.objectdb.o.LDR.E(LDR.java:470) at com.objectdb.o.LDR.z(LDR.java:269) at com.objectdb.o.OBC.aP(OBC.java:1058) at com.objectdb.o.OBC.aN(OBC.java:976) at com.objectdb.jpa.EMImpl.find(EMImpl.java:625) ... 2 more Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field profileMigration.classhierachychange.Test$NamedEntity.name to profileMigration.classhierachychange.Test$MyEntity at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source) at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(Unknown Source) at java.lang.reflect.Field.set(Unknown Source) at com.objectdb.o.UMR$T.E(UMR.java:1072) at com.objectdb.o.UMR$S.C(UMR.java:1015) at com.objectdb.o.UMR.B(UMR.java:603) ... 19 more
If you can see in the modified Code, i had tried to move the field name from NameEntity to MyEntity. (This didn't works too)
But very strange: It works after i changed the EntityModel again:
1) create the Database file
2) change the class hierarchy (now MyEnity extends BaseEntiy) -> thows the exeption.
3) change the class hierarchy (add field name to MyEnity) -> it works
or
1) create the Database file
2) change the class hierarchy (now MyEnity extends BaseEntiy and add field name to MyEnity)-> thows the exeption.
3) change the class hierarchy (remove field name from MyEnity) -> it works (but we lost the content of field 'name')
But this can not be the right way.