Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: ManyToOne mapped by composite natural key should be cached?
PostPosted: Mon Aug 29, 2016 3:06 pm 
Newbie

Joined: Wed Jun 22, 2016 1:17 pm
Posts: 7
Hi!

I've opened the following issue on JIRA:

https://hibernate.atlassian.net/browse/HHH-10936

and i wanted a clarification, but since the issue was closed i can't comment there anymore.

The issue said:

Quote:

@ManyToOne mapped by a composite natural key should be added to persistenceContext's entitiesByUniqueKey map

Code:
@Entity
public class Parent implements Serializable {
   private static final long serialVersionUID = 1L;

   @Id
   private Integer id;
   private Integer code;
   private Integer item;
}


Code:
@Entity
public class Child implements Serializable{
   
   private static final long serialVersionUID = 1L;

   @Id
   private Integer id;
   
   @ManyToOne(fetch=FetchType.LAZY)
   @JoinColumns({
      @JoinColumn(name="prop_code", referencedColumnName="code"),
      @JoinColumn(name="prop_item", referencedColumnName="item")
   })
   private Parent property;
}


When i load two different childs in the same session, and both reference the same parent, 4 queries are fired, 2 for the childs and 2 for the (same) parent.
In that case there should be only 3 queries, two for the childs, and one for the parent, as i believe the parent should be added to the persistenceContext entitiesByUniqueKey map after it is retrieved from the database for the first time.
If my assumptions are correct, a NAIVE fix would be to call persister.addEntity(euk, result) somewhere inside EntityType.loadByUniqueKey.
I've tried this already in a fork, and although it fixed the issue, when running the full suite of tests with H2, a (seemingly) unrelated test (org.hibernate.jpa.test.lock.LockTest.testContendedPessimisticLock) broke on cleanup, so since im extremelly new to Hibernate i have no idea of the side effects of my "fix".



Gail's answer says:

Quote:
Parent does not have a unique ID, so it cannot be added to persistenceContext's entitiesByUniqueKey.
Child has a non-unique many-to-one, as you mention that more than one Child can have the same parent. Since Child#parent is non-unique, it cannot be added to persistenceContext's entitiesByUniqueKey either.


Although I understand the answer, i believe that if i map a relation with manytoone, its implicit that the joincolumns must form a unique key in the referenced entity, am i missing something?

Anyway, i would like to know how can i tell hibernate that the Parent's code/item properties form a composite unique key, so they are hopefully added to persistenceContext's entitiesByUniqueKey.

Thanks!


Top
 Profile  
 
 Post subject: Re: ManyToOne mapped by composite natural key should be cached?
PostPosted: Sat Sep 10, 2016 10:54 am 
Newbie

Joined: Wed Jun 22, 2016 1:17 pm
Posts: 7
Hi! Any help?


Top
 Profile  
 
 Post subject: Re: ManyToOne mapped by composite natural key should be cached?
PostPosted: Sat Sep 10, 2016 11:18 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 890
For a @ManyToOne association, the FK should be unique, meaning that the "code" and the "item" combination should be unique.

In this case, you can use @NaturalId to mark that unique key on Parent.

Code:
@Entity
public class Parent implements Serializable {
   private static final long serialVersionUID = 1L;

   @Id
   private Integer id;

   @NaturalId
   private Integer code;

   @NaturalId
   private Integer item;
}


This might fix your issue. Let me know if it worked.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: ManyToOne mapped by composite natural key should be cached?
PostPosted: Wed Oct 19, 2016 9:19 am 
Newbie

Joined: Wed Jun 22, 2016 1:17 pm
Posts: 7
Hi vlad!

Thanks for the answer and sorry for the late reply (was assigned temporarily to another project).

The proposed solution didnt work, what I am using now is a fork of 5.1.1.Final where i replaced org.hibernate.type.EntityType.loadByUniqueKey(...).

The original return statement was:

Code:
return result == null ? null : persistenceContext.proxyFor( result );


My version does :

Code:
if ( result != null ) {
    persistenceContext.addEntity(euk, result);
    return persistenceContext.proxyFor(result);
}
return null;


However, even if it is working on my case and all of hibernate's tests still pass, i donĀ“t know, given my shallow understanding of hibernate's codebase, if this would be the correct approach.
Also, keeping a private fork of hibernate would be unfeasible to me.

Is this code modification correct? I proposed it on JIRA, but my issue was closed (i dont know if i made myself clear enough there).


Top
 Profile  
 
 Post subject: Re: ManyToOne mapped by composite natural key should be cached?
PostPosted: Mon Dec 12, 2016 12:49 pm 
Newbie

Joined: Wed Jun 22, 2016 1:17 pm
Posts: 7
Hi vlad!

Do you have any other idea ?

I'm about to remodel my entire DB layer as this issue cripples my app's performance, my fork works fine, but i believe it is going to be a headache on the long run, and i am not sure if it is the right approach ...

Thanks!


Top
 Profile  
 
 Post subject: Re: ManyToOne mapped by composite natural key should be cached?
PostPosted: Mon Dec 12, 2016 3:39 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 890
Make sure the composite keys are unique and then you'll have no issue.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 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:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.