2011-09-22 32 views
7

我的问题是关于JPA 2.0与Hibernate,@OneToOne关系和延迟加载。JPA 2.0/Hibernate:为什么用“@OneToOne”获取LAZY可以开箱即用?

首先我的设置:

  • 春3.0.5.RELEASE
  • SprnigData JPA 1.0.1.RELEASE
  • 的Hibernate 3.5.2决赛
  • DBMS:在PostgreSQL 9.0

我最近遇到这样一个事实,即@OneToOne关系不能以懒惰的方式获取(FetchType.LAZY),至少不是没有字节码的工具n,编译时间编织等。许多网站在那里说这一点,例如:

的事情是,我的设置中,@OneToOne实体的延迟加载似乎工作“开箱即用”,我真的很想理解为什么。请看看我的单元测试:

@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")); 
} 

这个测试用例是成功的,并在Hibernate的SQL日志输出,我可以清楚地看到,该“avatarImage”会不会牵强,只是“用户” (只是一个单一的SELECT,JOIN没有,到 “AvatarImage” 表等无法访问)

User类单向@OneToOne relationshop看起来是这样的:

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
private AvatarImage avatarImage; 

所以,一切都非常简单 - 它似乎工作。

重复我的问题:为什么它工作,为什么可以懒惰地提取“AvatarImage”,虽然它是由@OneToOne关联引用的?

我真的很感谢你可以提供的任何帮助

非常感谢!

回答

8

延迟加载OneToOne关系的问题仅在其反向部分(标记为mappedBy属性的部分)上。它在关系的拥有方面运作良好。 T 他在数据库级别上的区别很明显。在你的情况下,问题是如果用户数据库表中包含一个AvatarImage id作为其中一列或其他方式。 如果用户表有一个id为AvatarImage的列,那么延迟加载将按照你所说的“开箱即用”工作,但它不会以相反的方式工作。

3

当某种形式的字节码检测被执行时,惰性抓取可以在@OneToOne带注释的关系中与Hibernate JPA提供者一起使用。在你的情况下,我们可以排除构建时间检测(从你的评论中推断出它可以直接使用)。这给你带来了运行时编织的可能性,这在休眠& Spring中是很有可能的。在最近发布的Hibernate中,Javassist被用作Hibernate的运行时字节码工具框架,与CGLIB的另一种替代方案(which has been deprecated since Hibernate 3.5.5)相反。

Javassist是否在Spring中启用的问题很容易回答。 Hibernate EntityManager(它是委派给Hibernate Core的JPA 2.0提供者)需要Javassist,因此它应该位于Hibernate的类路径中,从而允许运行时编织这些类。您可以通过设置断点(在连接到应用程序服务器的远程调试器中)来确认这一点,并且您会注意到User类的Hibernate管理实例将不包含对AvatarImage实例的引用;相反,它会包含对名称类似于<package_name>.AvatarImage_$$_javassist_0(这是允许延迟获取的代理)的增强类的引用。

相关问题