views:

193

answers:

1

Hello,

I'm trying to add an object to a collection in my client view and to save it on server with hibernate/jpa mechanism.

Here is the problem: Take a Group object which can contains Account objects.

On my client view (gwt), I create a new group (so the id is null) and I add to this group some accounts (where ids exist). BUT these accounts are initialized in client with their id and pseudo only via a suggest box (because I don't want to load password and other stuff in my client view)

When my group returns to server, I try to save it with my dao and I've got this error: not-null property references a null or transient value

Here is my association in Group object:

@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public Set<Account> getAccounts()
{
    return accounts;
}

so the persist must be done automatically. But I think the problem is that I use partial account objects with existing id.

My question is: How can I add a simple association (just add a record in the manyToMany table) without loading all objects that I want to add (because I don't need it, I just want to add an association between two id)

EDIT: more information by example: I've got a group which properties are id:"G1" name:"group1"

I've got the account which properties are id:"A1" pseudo:"jerome" password:"pass1" status:"enabled" birthday:"xxxx" ...

From my client interface (done with gwt) I load the group1 object From an autcompletion I load Account objects but only with field id and pseudo (I don't want to load all the object). I add the Account object "Jerome" with id "A1" to my group.

I send my group to server to save it. In server I use a transactional method which save the group by calling: groupDAO.update(myGroup1)

As my Account object in this Group object is partially loaded, it causes an error.

So, How can I add the association between my group and account without loading the entire object Account ? I don't want this sort of code:

List newList = new ArrayList();
for (Account acc : myGroup1.getAccounts())
{
    Account accLoaded = accountDAO.findById(acc.getId());
    newList.add(accLoaded);
}

myGroup1.setAccounts(newList);
groupDAO.save(myGroup1);

thanks

+2  A: 

Hi Jerome,

Your goal:

I just want to add an association between two id without loading the entire object Account

You said:

I think the problem is that i use partial account objects with existing id

You are right. Suppose the following

public class Account {

    private Integer id;

    private Integer accountNumber;

    @Id
    public Integer getId() {
        return this.id;
    }

    @Column(nullable=false)
    public Integer getAccountNumber() {
        return this.accountNumber;
    }

}

So when you call

Group group = new Group();

// Notice as shown bellow accountNumber is null
Account account = new Account();
account.setId(1);

group.addAccount(account);

entityManager.persist(group);

So because of CascadeType.PERSIST, you are saying

Save each referenced Account

But each referenced Account accountNumber property is null. It explains why you get your exception

Instead of loading a fully initialized Account You can use something like

// If you do not want to hit the database
// Because you do not need a fully initialized Account
// Just use getReference method
Account account = entityManager.getReference(Account.class, new Integer(accountId));

So it does not make sense you load each fully initialized Account without any purpose or reason.

regards,

Arthur Ronald F D Garcia
Woa ! Exactly what I want !Thank you so much !
Jerome C.
+1, Perfect answer
Willi