views:

4619

answers:

2

I have a many-to-one association set up like this, in the hbm.xml:

<many-to-one name="gigVenue"
class="blah.blah.xxx" fetch="select"
lazy="no-proxy" not-null="true" >
<column name="N_VENUE_ID" precision="18" scale="0" not-null="true" />
</many-to-one>

And I am using instrumentation to do true lazy loading.

BUT when I run a hql query with an inner join fetch to the other table, the property that should contain the object that is the other table's value, is left as null. Even though I can see the other table's value's object being created by hibernate.

Does anyone have any insight into this problem?

update:

from Gig g inner join fetch g.gigVenue gv where g.artistId = :artistId and  (g.territoryId = -1 or g.territoryId = :territoryId) order by g.gigDatetime desc

<set name="gigs" inverse="true" lazy="true" table="DSP_GIG" fetch="select">
<key>
<column name="N_VENUE_ID" precision="18" scale="0" not-null="true" />
</key>
<one-to-many class="blah.blah.Gig" />
</set>
+1  A: 

Since you're using byte code instrumentation instead of association proxying (why?) you need to specify "fetch all properties" in your query:

from Gig g fetch all properties ...

Details are here

Update: Your gigVenue mapping is setting lazy to no-proxy. What that means is that property will be NULL until its first accessed via getter method. This is done using byte-code instrumentation and is not something that is commonly used. Using HQL join fetch will NOT populate such a property; you have to explicitly specify fetch all properties as I described above.

Consider setting lazy="proxy" instead (that's actually the default for many-to-one) which will initialize your property with a proxy object containing gigVenue identifier during the initial select, then retrieve the actual entity once you access one of GigVenue's methods. Using join fetch in HQL will also work in this case, fetching full GigVenue instance during the initial select.

On that note, setting fetch="select" is also questionable; you're most likely better off leaving it at the default join setting to enable using outer joins for fetching.

ChssPly76
Okay that is interesting. The reason we are using no-proxy is because one-to-one will always fetch otherwise (not always desirable). So it appears that for many-to-one use proxy but for one-to-one to have true lazy fetching use no-proxy and instrumentation.
Gilgad
and see http://stackoverflow.com/questions/965059/how-to-lazy-load-a-one-to-one-composition-via-hql for more info.
Gilgad
Unconstrained one-to-one is a special case. Take a look at this explanation https://www.hibernate.org/162.html if you haven't already. Bytecode instrumentation is indeed the only solution in that scenario, though to be honest I've never seen a case where selecting the other end of one-to-one association results in horrible performance - those are always PK-based.
ChssPly76
A: 

Instrumentation does not really affect queries and how they work. Why exactly are you doing the fetch in the query? Are you trying to speed things up?

And also a small question, just in case, how do you know the value is null? is that via the java debugger or is that by actually calling the "get" method? With instrumentation, the field will typically be null, until you actually ask for the field.

Michael Wiles
Yes I'm trying to stop a whole heap of hits to the db after the initial query.And yes I know the value would be fetched from the db once I called the getter but as I have already fetched the object (and I can see an object of that type created) why doesn't it just shove that in the property already?
Gilgad
Instrumentation does not affect queries, mappings do. I've updated my answer with a detailed explanation
ChssPly76