-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: oneotmany created twice
PostPosted: Thu Jul 22, 2010 7:12 am 
Newbie

Joined: Thu Sep 10, 2009 2:43 am
Posts: 7
Hi
I m using Hibernate to work with a local SQLServer.
These are my classes:
Person:
Code:
   @Id
   public String getId()
   @OneToOne(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
   public Metadata getMetadata()
   @OneToMany(mappedBy = "person", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
   public List<Nickname> getNicknames()

Nickname:
Code:
   @Id
   public String getId()
   @ManyToOne
   public Person getPerson()
   public String getNickname()

Metadata:
Code:
   @Id
   public String getId()
   @OneToOne(mappedBy="metadata")
   public Person getPerson()
   @CollectionOfElements(fetch = FetchType.EAGER)
   @MapKey(columns = @Column(name = "fieldKey", nullable = false))
   public Map<String, String> getMetadata()


I use this code to create the objects:
Code:
      Person p = new Person();
      p.setId("p1");
      p.setNicknames(new ArrayList<Nickname>());
      
      Nickname n= new Nickname();
      n.setId("n1");
      n.setPerson(p);
      n.setNickname("n1");
      p.getNicknames().add(n);
      
      Metadata metadata = new Metadata();
      metadata.setId("md1");
      metadata.setPerson(p);
      metadata.setMetadata(new HashMap<String, String>());
      metadata.getMetadata().put("n1", "v1");
      metadata.getMetadata().put("n2", "v2");
      
      p.setMetadata(metadata);
      
      personDao.create(p);


This creates all the raws in the DB as it should.

However, running this line:
Code:
System.out.println(pd.read("p1").getNicknames().size());

Prints "2", although there is only one Nickname raw in DB and in my creation code.

This is because Hibernate uses a select with Join with the Metadata_metadata table, which has two raws (n1=v1,n2=v2).

How does Hibernate know it should create only one Person object, and even only one Nickname object (although it gets two lines for the select), but puts the Nickname twice in the Nicknames list in that Person?

BTW - changing the Nicknames property to be a Set instead of a List works fine (but a Set is not good for me...).

Thanks
Yair


Top
 Profile  
 
 Post subject: Re: oneotmany created twice
PostPosted: Thu Jul 22, 2010 7:43 am 
Beginner
Beginner

Joined: Tue Jun 30, 2009 7:05 am
Posts: 29
Location: Italy
Hi Yair
I think it's beacause no side of Person-Nickname relation is marked as inverse.
Actually you have (speaking in ER language) a 1:N relation between Person and Nickname (one Person has 0...N nicks) and you map both sides of the relation.
You should mark as inverse the 1-side of the relation. The inverse="true" tells Hibernate not to persist the collection.
So Person becomes
Code:
   @Id
   public String getId()
   @OneToOne(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
   public Metadata getMetadata()
   @OneToMany(mappedBy = "person", fetch = FetchType.EAGER, cascade = CascadeType.ALL, [b]inverse="true"[/b])
   public List<Nickname> getNicknames()

(I never used the annotations, only XML mappings, so do not rely on the correctness of what I wrote)
Furthermore, you also set the cascade mode to always save related data.
I think that's the reason why you get two nicks associated to the person. One is saved by the Person (when the Nicknames collection is persisted) and one by the Nickname entity.

Stefano


Top
 Profile  
 
 Post subject: Re: oneotmany created twice
PostPosted: Thu Jul 22, 2010 12:01 pm 
Newbie

Joined: Thu Sep 10, 2009 2:43 am
Posts: 7
Stefano,
Thanks for your answer.
The "inverse" property (which I couldn't find by the way...) is no good for me - I want Hibernate to persist the Nicknames when persisting a Person.

Yair


Top
 Profile  
 
 Post subject: Re: oneotmany created twice
PostPosted: Fri Jul 23, 2010 2:59 am 
Beginner
Beginner

Joined: Tue Jun 30, 2009 7:05 am
Posts: 29
Location: Italy
I think that if you have a relation mapped on both sides you must set one side as inverse.
The <many-to-one> cannot be inverse, so I think you do not have many choices.
The reference docs point it out: http://docs.jboss.org/hibernate/core/3. ... usingbidir

Bye,
Stefano


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.