Persisting collection where members are subclasses

#1

OK, I have a number of classes which are all subclasses of Entry (e.g., Folder, Link, Book). In the Folder class, there is a @OneToMany Map<String, Entry> children

If I store something in that map which is an Entry, then I can persist just fine. But if I try to put any of the subclasses into the map, then I get 

[ObjectDB 2.3.6] javax.persistence.RollbackException
Failed to commit transaction: Attempt to persist a reference to a non managed com.typowebguide.directory.Folder instance - field com.typowebguide.directory.Folder.children (error 613)

is this a bug in ObjectDB or should I be handling this differently? Would this work better using JDO rather than JPA?

-dh

#2

Polymorphism is supported by ObjectDB, and you shouldn't have any problem in persisting a map with different value types.

The error message may indicate that the map values include entity objects that have not been persisted. You have to persist every entity object explicitly unless cascading persist is enabled (it is enabled by default in JDO, but that is the only difference between JPA and JDO in this context).

If you still cannot make it work  - post a test case.

ObjectDB Support
#3

I've attached my key classes. 

Here's the test case which is failing:

@Test
public void canRetrieveFolderByName() {
  Folder f = new Folder("A");
  f.addChild(new Folder("B"), "B");
  f.addChild(new Folder("C"), "C");
  System.err.println(f.getChildren());
 
  entityManager.getTransaction().begin();
  entryDao.makePersistent(f);
  entityManager.getTransaction().commit();

  List<Entry> savedEntries = entryDao.findAll();
  System.err.println(savedEntries);
  System.err.println(((Folder)savedEntries.get(0)).getChildren());
  List<Folder> loadedFolders = entryDao.findFolderByName("B");
  Assert.assertEquals(1, loadedFolders.size());
  Assert.assertEquals(f, loadedFolders.get(0));
}
#4

The following test seems to work fine:

import java.util.*;

import javax.persistence.*;


public class T728 {

    public static void main(String[] args) {
        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory(
                "objectdb:db/test.tmp;drop");
        EntityManager em = emf.createEntityManager();

        Folder f = new Folder("A");
        f.addChild(new Folder("B"), "B");
        f.addChild(new Folder("C"), "C");
      
        em.getTransaction().begin();
        em.persist(f);
        em.getTransaction().commit();
       
        em.close();
        emf.close();
    }

    @Entity
    public static class Entry {
    }
   
    @Entity
    public static class Folder extends Entry {
        String name;
        @OneToMany(cascade=CascadeType.PERSIST)
        private Map<String,Entry> children = new HashMap<String,Entry>();

        Folder(String name) {
           this.name = name;
        }

        public void addChild(Folder folder, String key) {
            children.put(key, folder);
        }
    }
}

Try to change it to demonstrate the problem. Unfortunately very little can be done with a non runnable test as the one that you have published at #3.

ObjectDB Support

Reply