Search code examples
inheritanceormjdodatanucleus

How to map a List of child classes while having the @Element annotation's column in the parent class?


I have an class with 2 different Lists. Each List uses a different class as it's generic type. These classes share the same base class. When I try to persist my class that contains both lists I get an error explaining that the column specified in the @Eelement annotation doesn't exist in each of the child classes. But this column exists in the parent class. So how can I tell datanucleus that this column is in the parent class and not the child classes ?

Base class:

@PersistenceCapable(table = "Z")
@Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
public abstract class Z {
    @Persistent(primaryKey = "true", valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;

Child classes

@PersistenceCapable(table = "X")
@Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
public class X extends Z {

@PersistenceCapable(table = "Y")
@Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
public class Y extends Z {

The class I'm trying to persist:

@PersistenceCapable(table = "MyClass")
public class MyClass {
    @Persistent(column = "id", primaryKey = "true", valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;
    // Specifies the FK column pointing to this object (ie. MyClass)
    @Element(column = "myclass_id")
    @Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering", value = "order ASC"))
    private List<X> xList;

    // Specifies the FK column pointing to this object (ie. MyClass)
    @Element(column = "myclass_id")
    @Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering", value = "order ASC"))
    private List<Y> yList;

This is part of the stacktrace I get when I try to persist MyClass. The whole stacktrace repeats the same information more than once for both child class tables so I just mentioned a part of the stackstrace:

Required columns missing from table "ipk.x" : myclass_id. Perhaps your MetaData is incorrect, or you havent enabled "datanucleus.schema.autoCreateColumns".
org.datanucleus.store.rdbms.exceptions.MissingColumnException: Required columns missing from table "ipk.x" : myclass_id. Perhaps your MetaData is incorrect, or you havent enabled "datanucleus.schema.autoCreateColumns".
    at org.datanucleus.store.rdbms.table.TableImpl.validateColumns(TableImpl.java:277)
    at org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.performTablesValidation(RDBMSStoreManager.java:3421)
    at org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.addClassTablesAndValidate(RDBMSStoreManager.java:3218)
    at org.datanucleus.store.rdbms.RDBMSStoreManager$ClassAdder.run(RDBMSStoreManager.java:2871)
    at org.datanucleus.store.rdbms.AbstractSchemaTransaction.execute(AbstractSchemaTransaction.java:119)
    at org.datanucleus.store.rdbms.RDBMSStoreManager.manageClasses(RDBMSStoreManager.java:1608)
    at org.datanucleus.store.rdbms.RDBMSStoreManager.getDatastoreClass(RDBMSStoreManager.java:678)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.getDatastoreClass(RDBMSPersistenceHandler.java:88)
    at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.insertObject(RDBMSPersistenceHandler.java:123)
    at org.datanucleus.state.StateManagerImpl.internalMakePersistent(StateManagerImpl.java:3489)
    at org.datanucleus.state.StateManagerImpl.makePersistent(StateManagerImpl.java:3465)
    at org.datanucleus.ExecutionContextImpl.persistObjectInternal(ExecutionContextImpl.java:2031)
    at org.datanucleus.ExecutionContextImpl.persistObjectWork(ExecutionContextImpl.java:1874)
    at org.datanucleus.ExecutionContextImpl.persistObject(ExecutionContextImpl.java:1722)
    at org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:722)
    at org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:747)
    at ...

Solution

  • So what is the "myClass" field in Z doing? Maybe it is supposed to be part of a BI-directional relation? In which case mappedBy is supposed to be specified at the owner side (the List(s)). Being part of a bidirectional relation is the only way you can make use of that column in Z for storing the FK for the List relation(s).

    Also there is no "order" field in Z (specified as part of the List(s)) so that part wouldn't work either.