Question

I have the following case:

An "Account" class, which should contain a colleciton of "Money" objects.

@PersistenceCapable
public class Account extends Entity {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
    private String id;

    @Expose
    @Persistent
    private String name;

    /**
     * The initial balance should be a portfolio, e.g. 300 BGN, 230 EUR etc.
     */
    @Expose
    @Persistent
    private List<Money> initialBalancePortfolio;

The "Money" class looks this way:

public class Money {
    @Persistent
    @Extension(vendorName = "datanucleus", key = "gae.unindexed", value = "true")
    private BigDecimal ammount;

    @Persistent
    private String currency;

Here come the problems:

  1. I do not want a separate table for all money instances. I tried to achieve it as I used @Embedded annotation, but it was not possible since initialBalancePortfolio cannot be embedded itself (Collection).
  2. I gave up and tried to store the account object (pm.makePersistent(...)). I was hoping that this way the money object will be stored as well. This was actually true, but all of the object fields were null.

This test case shows the issue:

    @Test
    public void initialBalancePortfolioShouldBePersisted() throws Exception {
        //create
        Account account = createAccount();
        AccountDao accountDao = new AccountDao();
        accountDao.create(account);
        //get it with new dao
        AccountDao newAccountDao = new AccountDao();
        Account newAccount = newAccountDao.readAll().get(0);
        assertEquals(account.getInitialBalancePortfolio(), newAccount.getInitialBalancePortfolio());
    }

    private Account createAccount() {
        //create list with money
        List<Money> money = new ArrayList<Money>();
        Money m1 = new Money(23, "BGN");
        Money m2 = new Money(21, "EUR");
        money.add(m1);
        money.add(m2);
        //create account 
        Account account = new Account(accEntity, money, "xxx");
        return account;
    }

And JUnit Exception:

java.lang.AssertionError: expected:<[Money [ammount=23, currency=BGN], Money [ammount=21, currency=EUR]]> but was:<[Money [ammount=null, currency=null], Money [ammount=null, currency=null]]>

EDIT:

Persistence code for object creation:

/**
 * Create entity. entityDao.create(entity);
 * 
 * @param t
 *            Entity
 * @return operations success
 */
public boolean create(T t) {
    if (t.getId() == null) {
        PersistenceManager pm = PMF.getInstance().getPersistenceManager();
        try {
            pm.makePersistent(t);
            LOGGER.info(getEntityClass() + " created!");
            return true;
        } finally {
            pm.close();
        }
    } else {
        LOGGER.info(getEntityClass() + " already exist! Update only!");
        update(t);
        return false;
    }
}

and for object retrieval:

/**
 * Get all existing objects.
 * 
 * @return
 */
public List<T> readAll() {
    PersistenceManager pm = PMF.getInstance().getPersistenceManager();
    try {
        pm.getFetchPlan().setGroup(FetchGroup.ALL);
        Query q = pm.newQuery(getEntityClass());
        @SuppressWarnings("unchecked")
        List<T> allEntities = (List<T>) q.execute();
        return allEntities;
    } finally {
        pm.close();
    }
}
Was it helpful?

Solution

I have found a solution to the problem.

Some background information about how JDO manages the lifecycle of an object: http://db.apache.org/jdo/state_transition.html

And the solution itself:

PersistenceManager pm = PMF.getInstance().getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
    tx.begin();
    pm.makePersistent(t);
    tx.commit();
} catch (Exception e) {
    LOGGER.severe("Exception by creating a new entity "
            + e.getMessage());
    tx.rollback();
} finally {
    pm.close();
}

As you can see, I am using a transaction to ensure that the object is in a valid state.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top