karanpal-dhillon / datanucleus-appengine

Automatically exported from code.google.com/p/datanucleus-appengine
0 stars 0 forks source link

Persisting JPA @ElementCollection of Embeddables #318

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
I am trying to persist a JPA entity with a collection of custom (enhanced) 
@Embeddable objects using the JPA2 @ElementCollection annotation:

@Entity
public class TestEntity {
    @ElementCollection
    private List<TestEmbeddable> testEmbeddables;
    ...
}

@Embeddable
public class TestEmbeddable implements Serializable {
    public String s;
}

While this does not result in an error message, the persisted Datastore entity 
will only contain a collection of null values instead of a representation of 
the actual objects: TestEntity.testEmbeddables = [null, null, ...]. Doing this 
with a collection of Strings works fine: TestEntity.testStrings = [str1, str2, 
...].

If I replace @ElementCollection with @Embedded, the field s of the Embeddables 
is persisted as TestEntity.s.0, TestEntity.s.1, etc., but the JPA 
implementation won't be able to track changes to the collection. Again, with a 
collection of Strings, the result is the same as with @ElementCollection.

(App Engine SDK 1.7.7.1, datanucleus 3.1.3, datanucleus-appengine 2.1.2)

See also: 
http://stackoverflow.com/questions/16177009/persisting-elementcollection-of-embe
ddable-google-app-engine-datanucleus

Original issue reported on code.google.com by geiger....@gmail.com on 25 Apr 2013 at 12:19

GoogleCodeExporter commented 8 years ago
as refered in the stackoverflow link, @embedded works,
but @ElementCollection is the interoperable standard.
http://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/ElementCollections

Original comment by wokier on 19 Jun 2013 at 7:12

GoogleCodeExporter commented 8 years ago
@Embedded used on a collection only works when there is no data.
When i try to retrieve them, i get:
javax.jdo.JDOFatalUserException: No metadata has been registered for class 
"[EmbeddedClass]"

The only workaround i got now is to clean the data with the datastore viewer, 
and then re-persist my data.

Original comment by wokier on 17 Jul 2013 at 10:12

GoogleCodeExporter commented 8 years ago
Have you enhanced the @Embeddable classes, e.g., by adding them to 
persistence.xml?

Original comment by geiger....@gmail.com on 17 Jul 2013 at 11:32

GoogleCodeExporter commented 8 years ago
I have tried with and wthout this declaration.
It does not change anything.
I am thinking about registering them manually throught
JDOImplHelper.registerClass but it needs som reflections stuff to retrieve 
filds and types, and i don't know when to call it (before or after the 
EntityManager creation).

Original comment by wokier on 17 Jul 2013 at 12:22

GoogleCodeExporter commented 8 years ago
I have discovered that registerClass is called by enhanced class. But this was 
not done for the embeddedable classes, so i have put this code beetwen the 
EntityManagerFactory creation and the EntityManager creation:

for (Class embeddableClass : new 
Reflections("your.entities.package").getTypesAnnotatedWith(Embeddable.class)) {
    try {
        System.out.println(embeddableClass.newInstance());
    } catch (InstantiationException e) {
        LOGGER.warning(e.getClass() + " " + e.getMessage());
    } catch (IllegalAccessException e) {
        LOGGER.warning(e.getClass() + " " + e.getMessage());
    }
}

and it works (with @Embedded)

Original comment by wokier on 18 Jul 2013 at 1:58