oct*_*cty 7 java hibernate jpa
想象一下关系数据库中的2个表,例如Person和Billing.在这些实体之间定义了(非强制性)OneToOne关联,并且它们共享Person主键(即PERSON_ID在Person和Billing中定义,并且它是后者中的外键).
通过命名查询对Person进行选择时,例如:
from Person p where p.id = :id
Run Code Online (Sandbox Code Playgroud)
Hibernate/JPA生成两个选择查询,一个在Person表上,另一个在Billing表上.
上面的示例非常简单,并且不会导致任何性能问题,因为查询只返回一个结果.现在,假设Person有nOneToOne关系(均非强制性)与其他实体(所有共享Person主键).
如果我错了,请纠正我,但是select在Person上运行查询,返回r行,将导致(n+1)*rHibernate生成选择,即使这些关联是懒惰的.
是否存在针对此潜在性能灾难的解决方法(除了根本不使用共享主键)?谢谢你的所有想法.
想象一下关系数据库中的2个表,例如Person和Billing.这些实体之间定义了(非强制性)OneToOne关联,
对于非强制性OneToOne,默认情况下,懒惰提取在概念上是不可能的,Hibernate必须访问数据库才能知道关联是否null存在.来自这个旧维基页面的更多细节:
关于延迟加载的一些解释(一对一)
[...]
现在考虑我们的B类与C有一对一的关联
Run Code Online (Sandbox Code Playgroud)class B { private C cee; public C getCee() { return cee; } public void setCee(C cee) { this.cee = cee; } } class C { // Not important really }在加载B之后,你可以调用
getCee()获得C.但是看,getCee()是你的类的一种方法,而Hibernate无法控制它.Hibernate不知道有人什么时候打电话getCee().这意味着Hibernate必须cee在从数据库加载B时将适当的值放入" "属性中.如果启用了代理C,Hibernate可以放置一个尚未加载的C代理对象,但会在有人使用它时加载.这给了延迟加载one-to-one.但现在想象你的
B对象可能有也可能没有关联C(constrained="false").我应该getCee()返回特定的时候B没有C?空值.但请记住,Hibernate必须在设置时设置正确的"cee"值B(因为它不知道何时会有人打电话getCee()).代理在这里没有帮助,因为代理本身已经是非null对象.所以简历:如果你的B-> C映射是强制性的(
constrained=true),Hibernate将使用C代理导致延迟初始化.但是如果你允许B没有C,那么Hibernate只是在它加载B时检查C的存在.但是检查存在的SELECT效率很低,因为相同的SELECT可能不仅仅检查存在,而是加载整个对象.懒惰的装载消失了.
所以,不可能......默认情况下.
是否存在针对此潜在性能灾难的解决方法(除了根本不使用共享主键)?谢谢你的所有想法.
问题不是共享主键,无论是否有共享主键,你都会得到它,问题是可以为空的 OneToOne.
第一个选项:使用字节码检测(参见下面的文档参考)和无代理提取:
@OneToOne( fetch = FetchType.LAZY )
@org.hibernate.annotations.LazyToOne(org.hibernate.annotations.LazyToOneOption.NO_PROXY)
Run Code Online (Sandbox Code Playgroud)
第二种选择:使用假货ManyToOne(fetch=FetchType.LAZY).这可能是最简单的解决方案(据我所知,推荐的解决方案).但我没有用共享的PK测试这个.
第三个选项:使用a预先加载结算join fetch.
| 归档时间: |
|
| 查看次数: |
5091 次 |
| 最近记录: |