Michael Weber
Michael Weber

Reputation: 53

Hibernate - changing attributes of an existing object

Consider the following situation. I have an object which is persisted by hibernate. The object has a bunch of object attributes which itself have a ton of attributes themselves. Like so:

Mainobject
|-Subobject A
|--String xyz
|-- ...
|-Subobject B
|-- ...
|-Subobject C
|- ...

The main object table pretty much just references the sub object tables.

Saving and loading the object is no issue, neither updatig when I change the values of a subobject attribute, like xyz for example. However, I sometimes have to create new instances of all the subobjects and assign those new subobjects to the existing main object. When I saveOrUpdate the main object I (obviously) get a new row for each of the subobjects and the main object is updated with the new references.

What I want to achieve instead, however, is that Hibernate doesnt create new rows for the new objects but just updates the old rows instead.

How can I achieve this? (I could just load the subobject and assign all its new attributes manually, but there is a plethora of them and that doesnt really seem a good way to do it)

Thank you!

edit: Very basic sample code

Mainobject obj = dao.get(MainObject.class, 1L);
obj.setSubobjectA(new SubobjectA());
obj.setSubobjectB(new SubobjectB());
dao.saveOrUpdate(obj);

another edit: There is no combined keys. Every object/table has a single PK. The Mainobject Table holds the references/foreign keys to the subobject tables.

edit (for user 226..): This is how the main object looks:

@Entity
@Table(name="mainobjects")
public class MainObject 
{
    @Id @GeneratedValue
    private Long mainOjectId;

    @OneToOne
    @JoinColumn(name="ref_subobjectA_id")
    @Cascade({CascadeType.SAVE_UPDATE})
    private SubobjectA subobjectA;

    @OneToOne
    @JoinColumn(name="ref_subobjectB_id")
    @Cascade({CascadeType.SAVE_UPDATE})
    private SubobjectB subobjectB;

// getters / setters
}

This is how subobjectA looks:

@Entity
@Table(name="subobjectsa")
public class SubobjectA 
{
    @Id
    private String subobjectaId;
    private String str1;
    private String str2;
    private String ....
...
// getters/setters
}

SubobjectB looks pretty much the same.

In the code Im looking whether the object exists:

List<MainObject> existingMainObjects = dao.findByAttributes(MainObject.class, attributeNames, attributeValues);

If it doesnt I just save, no problem. If it does exist im replacing the subobjects in the existing Mainobject with subobjects of another mainobject (which isnt persisted in the db):

if (existingMainObjects.size() == 1)
{
existingMainObjects.get(0).setSubobjectA (someNewMainObject.getSubobjectA);
existingMainObjects.get(0).setSubobjectB (someNewMainObject.getSubobjectB);

dao.saveOrUpdate(existingMainObjects.get(0));
}

To reiterate: This creates no new entry for mainobject, but for the subobjects (because its a different object than the one persisted by Hibernate) it creates new ones and updates the main object with the new references. What I want to achieve basicallly is that only the values in the subobjects are replaced.

My current workaround includes using beanutils to copy all the properties but the key from the new object into the existing object. This works, but is probably very inefficient when you have to do this several tenthousand times.

Edit: Temporary solution Ok I was thinking using merge instead of saveOrUpdate on the MainObject should do the trick. But it doesnt. I then decided to try using the merge function on each subobject indidvidually. This seems to work for some reason. Can anyone explain why it doesnt work when I just merge the main object?

Upvotes: 0

Views: 1257

Answers (1)

Mukesh S
Mukesh S

Reputation: 2886

You are setting two new objects to MainObject. Now when you set new objects at foreign key, since you said your MainObjecct references SubobjectA and SubobjectB, Hibernate will search for these objects at the main Table i.e SubobjectA and SubobjectB. If it finds any match then its fine, other wise it will create new enrties there(SubobjectA and SubobjectB separately) and insert your MainOject.

What you can do is, put only those objects(SubobjectA and SubobjectB) in MainObject that are already present in SubobjectA and SubobjectB. For new entries, first insert in SubobjectA and SubobjectB then in the MainObject.

Upvotes: 1

Related Questions