my question is regarding JPA 2.0 with Hibernate, @OneToOne relationships and lazy loading.
First my setup:
- Spring 3.0.5.RELEASE
- SprnigData JPA 1.0.1.RELEASE
- Hibernate 3.5.2-Final
- DBMS: PostgreSQL 9.0
I recently came across the fact, that a @OneToOne relationship can’t be fetched the lazy way (FetchType.LAZY), at least not without byte code instrumentation, compile time weaving or the like. Many sites out there say this, for example:
- http://community.jboss.org/wiki/SomeExplanationsOnLazyLoadingone-to-one
- http://justonjava.blogspot.com/2010/09/lazy-one-to-one-and-one-to-many.html
- Making a OneToOne-relation lazy
The thing is, with my setup, a lazy loading of a @OneToOne entity seems to work “out of the box”, and I really would like to understand why. Please, have a look at my unit test:
@Test
@Transactional
public void testAvatarImageLazyFetching()
{
User user = new User();
user.setAvatarImage( new AvatarImage() );
User = userRepository.save( user );
entityManager.flush();
entityManager.clear();
User loadedUser = userRepository.findOne( user.getId() );
assertNotNull( loadedUser );
PersistenceUtil persistenceUtil = Persistence.getPersistenceUtil();
assertTrue( persistenceUtil.isLoaded( loadedUser ) );
assertFalse( persistenceUtil.isLoaded( loadedUser, "avatarImage" ) );
}
This test case is successful, and in Hibernates SQL logging output, I can see clearly, that the “avatarImage” will not be fetched, just the “user” (just a single SELECT, no JOIN, no access to the “AvatarImage” table etc.)
The unidirectional @OneToOne relationshop in the User class looks like this:
@OneToOne( cascade = CascadeType.ALL, fetch = FetchType.LAZY )
private AvatarImage avatarImage;
So, everything very simple – and it seems to work.
To repeat my question: why is it working, why can the “AvatarImage” be fetched lazily, although it is referenced with a @OneToOne association?
I really appreciate any help you can offer
Thanks a lot!
The problem with lazy loading of OneToOne relationship is only on the inverse part of it (the one which is marked with mappedBy attribute). It works fine on the owning side of the relationship. T
he difference between those is clear on database level. In your case the question is if the User database table holds an id of AvatarImage as one of the columns or the other way round.
If User table has a column with an id of AvatarImage then the lazy loading will work as you said “out-of-box” but it will not work the other way round.