can't get HashMap out of the database

#1

I'm trying to persist an Entity containing a HashMap. It stores the data in the database OK, but the map is always empty when I get the entity out of the database again.

I've reproduced this problem in a simple variation of the Guestbook tutorial:

Guest class:

=====================

@Entity
public class Guest implements Serializable {
    private static final long serialVersionUID = 1L;

    // Persistent Fields:
    @Id @GeneratedValue
    Long id;
    private String name;
    private Date signingDate;
    private HashMap<String, String> map = new HashMap<String, String>();

    // Constructors:
    public Guest() {
    }

    public Guest(String name) {
        this.name = name;
        this.signingDate = new Date(System.currentTimeMillis());
        map.put(name, signingDate.toString());
       
    }

    // String Representation:
    @Override
    public String toString() {
        return name + " : signed on " + signingDate +
            "; from map : " + map.get(name);
    }

==========================

GuestDao is the same as the tutorial

Test class:

==========================

public class GuestTest {
    private GuestDao guestDao;

    @Test
    public void test() {
        ClassPathXmlApplicationContext context =
            new ClassPathXmlApplicationContext(
                new String[] { "spring-servlet.xml" });
 
        guestDao = context.getBean(GuestDao.class);
        Guest tst = new Guest("testname");
        guestDao.persist(tst);
        List<Guest> result= guestDao.getAllGuests();
        System.out.println(result.get(0).toString());
    }
}

================

Please advise what I need to do to get the map.

The full Eclipse project attached FYI.

Thanks,

Natalia.

 

 

#2

Try annotating the map with @OneToMany(fetch=FetchType.EAGER).

Outside the DAO method only fields that have already been loaded are available, unless you use a Container-managed Extended Persistence Context, as discussed in this forum thread.

In addition, you have to use the last build (2.3.2_04), since due to a bug (issue #552) eager load didn't work for collections and maps of simple values.

ObjectDB Support
#3

Thanks for your response. The simple test is now working, however the actual code I am trying to get going is considerably more complicated and it is still not working. It involves nested embeddable objects. I've modified the test code  to be a bit closer to the actual code and I am now getting a null pointer exception trying to access the map in the nested object:

java.lang.NullPointerException
at com.objectdb.o.TYR.<init>(TYR.java:101)
at com.objectdb.o.ENT.newTypeReader(ENT.java:1186)
at com.objectdb.o.TYT.extractMap(TYT.java:57)
at com.objectdb.o.ENT.extractMap(ENT.java:1249)
at objectdb.java.util.HashMap.__odbBeforeAccess(Unknown Source)
at objectdb.java.util.HashMap.values(Unknown Source)
at guest.Guest.toString(Guest.java:42)
at guest.Guest.toString(Guest.java:52)
at guest.GuestHolder.toString(GuestHolder.java:32)
at guest.GuestTest.test(GuestTest.java:25)

The Guest object is:

@Embeddable
public class Guest implements Serializable {
    private String name;
    private Date signingDate;
    @OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    private HashMap<String, Guest> map = new HashMap<String, Guest>();

.............................

The GuestHolder is:

@Entity
public class GuestHolder {
    // Persistent Fields:
    @Id @GeneratedValue
    Long id;

    @OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    private ArrayList<Guest> guests = new  ArrayList<Guest>();

................................................

The test:

@Test
public void test() {
    ClassPathXmlApplicationContext context =
        new ClassPathXmlApplicationContext(
            new String[] { "spring-servlet.xml" });
 
    guestDao = context.getBean(GuestDao.class);
    GuestHolder hld = new GuestHolder();
    Guest tst = new Guest("testname");
    Guest l2 = new Guest("level 2");
    tst.addGuest(l2);
    Guest l3 = new Guest("level 3");
    l2.addGuest(l3);
    hld.getGuests().add(tst);
    guestDao.persist(hld);
    List<GuestHolder> result= guestDao.getAllGuestHolders();
    System.out.println(result.get(0).toString());
}

The full project attached.

Please advise if nested embeddable objects are supported.

Kind regards,

Natalia.

#4

Nested embedded is supported and your new test works with version 2.3.2_05.

Your test project, however, uses an older version (2.2.5). Please verify that you do not have references to older ObjectDB versions in both the pom.xml and the .classpath files.

ObjectDB Support
#5

I've tried it with 2.3.2_05 and it does not throw the exception anymore. However, the "level 3" nested object in the same test case is not returned, even though it gets stored in the database. The updated project attached.

Regards,

Natalia.

#6

You are right, there was a problem with eager fetch of maps. Please try build 2.3.2_06.

ObjectDB Support
#7

Thanks for the fix, the test project now works. However my actual code is still not working. I have cut out a piece of my actual project that demonstrates the problem, please see attached. If you run the test in /Guestbook/src/main/java/guest/audit/AuditDAOImplTest.java you can see that the AuditRecord saved to the database has contact details in it, but when I retrieve it from the database it does not have contact details. 

Regards,

Natalia.

#8

Build 2.3.2_08 fixes another problem and your new test passes if HashMap is replaced with TreeMap (this is required since HashMap doesn't preserve order so the result strings may be different).

ObjectDB Support
#9

Thanks, it all works now

Natalia

#10

Good. Thank you for this bug report and for the tests.

ObjectDB Support

Reply