How to map a unidirectional Many-To-One association using a HashSet


#1

Hi folks,
We are facing a big problem…

We got a Java object like this : Beneficiaire contains RessourceRGAL.

 public class Beneficiaire extends BaseBean
 {
     ...  
     private Set<RessourceRGAL> lesRessourceRGAL = new HashSet<RessourceRGAL>();
 }

Mapping hbm file is described like this :

hibernate-mapping package="bean.beneficiaire" default-lazy="true" default-cascade="none"
class optimistic-lock="version" table="beneficiaire_bene" name="Beneficiaire"
... 
set name="lesRessourceRGAL" table="ressourcergal_rrga"
key foreign-key="fk_rrga_bene_1" 
column name="bene_id_lesressourcergal" index="in_rrga_5" not-null="false"column
/key
one-to-many class="bean.RessourceRGAL" /
/set

When reading the collection, we restrict the results, for instance on a specific year. Thus, the collection is barely never complete.

Let’s say we’ve found just one object for the year 2018.
If we want to delete this element of the collection:

unBeneficiaire.getlesRessourceRGAL().remove(unRessourceRGAL)

and now synchronizing with the database

saveorupdate(unBeneficiaire)

Here is what Hibernate does :

update ressourcergal_rrga set bene_id_lesressourcergal=null where bene_id_lesressourcergal=?

Which means that if we had some RessourceRGAL for other years, they now have become orphans.

Same problem when finding no object at all for a year ; we have to create them with

unBeneficiaire.setLesRessourceRGAL(new HashSet());

saveorupdate(unBeneficiaire)

Hibernate is gonna put all FK to null.

Is there a way to avoid this behaviour?

Best regards,
Thomas (France)


#2

Sorry, I had to take away < and > characters for the hbm file :((((


#3

You never have to do that. The collections should always be initialized to an empty collection and never be null. More, you should never reset a collection by replacing it with a new collection object.

The problem you are facing there is due to the fact that you are using unidirectional collections, and not inverse ones.

You should switch to bidirectional collections, as explained in this article because they are more efficient and don’t even require an intermediary table.


#4

Dear vlad, thanks for your answer.
I’m not sure I got it all.

You say my collection should be initialized to an empty collection ; that’s what we’ve tried. Hibernate uses a PersistentSet, I tried a Collections.emptySet(). But nothing worked after this.

I’ll read your articles (I’ve already read some!!!) to try to understand a bit more…

Regards,
Thomas


#5

First of all, you might want to add the data access logic you are using.

Second, related to your comment:

You say my collection should be initialized to an empty collection ; that’s what we’ve tried. Hibernate uses a PersistentSet, I tried a Collections.emptySet(). But nothing worked after this.

Hibernate uses PersistentSet, but initializing the field as a HashSet will simplify the data access logic since you don’t have to check it for null every time you want to add/remove a value.


#6

Dear vlad,
this message just to let you know…it now works fine.
We’d have been trapped without your help.

Thanks again.

Best regards,
Thomas


#7

I’m glad it works fine now. But, you should mark the answer which led to the solution rather than the one saying that it works now.


#8

Hi,
you’re right…thing done now.
Take care.
Thomas


#9

FYI, java.util.Collections.emptySet() returns an immutable Set.