Hibernate 没有在反面缓存我的 OneToOne 关系
我的代码如下:
@Entity
@Table(name = "A")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class A
{
@OneToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGER, mappedBy="a")
public B getB() {};
}
@Entity
@Table(name = "B")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class B
{
@OneToOne(cascade={}, fetch=FetchType.LAZY)
@JoinColumn(name="A_ID")
public A getA() {};
}
每次加载 A
时,都会查询 B
。为什么A
加载后A.getB()
没有被缓存,是否可以缓存?
I have code like:
@Entity
@Table(name = "A")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class A
{
@OneToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGER, mappedBy="a")
public B getB() {};
}
@Entity
@Table(name = "B")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class B
{
@OneToOne(cascade={}, fetch=FetchType.LAZY)
@JoinColumn(name="A_ID")
public A getA() {};
}
each time when A
is loaded there is query for B
. Why is A.getB()
not cached after A
is loaded and is it possible to cache it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对我有用的解决方法是使用 @OneToMany 创建额外的方法
,我对此解决方案不太满意,但它有效,而且我找不到其他方法。
Workaround that work for me is create additional method with @OneToMany
I'm not very happy with this solutions, but it works and I can't find other way.
尝试将 @Cache 注释也放在 getB() getter 上。我的观察是,如果您缓存该对象,它的关联可能不会被视为缓存。
Try putting @Cache annotation on getB() getter as well. My observations are that if you cache the object, it's associations may not be considered cached.
这可能需要更多工作,但您可以尝试使 fetchType Lazy,并且
显式地获取 B。这样你就可以检查B的实例是否已经加载了?
顺便说一句,你看过这篇文章吗?我认为问题是类似的:
https://forum.hibernate.org/viewtopic.php? p=2378461
It may be a little more work, but you could try making the fetchType Lazy, and
do the fetching of B explicitly. That way you could check whether the instance of B has already been loaded or not?
On a side note, have you seen this post? I think the problem is similar:
https://forum.hibernate.org/viewtopic.php?p=2378461
我觉得原来的答案并没有完全解释为什么会发生这种情况。
为什么 OneToOne 不被缓存?
它不被缓存是因为
A 类
不是关系的所有者,并且其表中不包含 @JoinColumn。因此,A 类
无法得知B 类
的ID
是什么。这就是为什么当尝试检索class A
时,它需要发送对class B
的查询来找出B类的ID是什么,但是当它发送查询时B 类
已加载,因此无需实际从缓存中检索它。何时缓存 OneToOne?
现在,如果您以相反的方式从
B 类
导航到A 类
,那么您将立即访问缓存:)为什么 @OneToMany(cascade={}, fetch=FetchType.EAGER,mappedBy="a") 有效?
在 hibernate 中,集合被缓存在称为集合缓存的专用区域中。 Hibernate 缓存组成集合的实体的主键。不是实体本身;即二级缓存中没有存储任何Set。
一旦从集合缓存区域检索到主键,它就会回退到常规实体缓存以检索实际对象。因此,
@OneToMany
hack 适合您。I feel that the original answer does not cover entirly why this is happening.
Why OneToOne is not cached ?
It is not cached because
class A
is not the owner of the relationship and does not contain the @JoinColumn inside its table. Therefore there is no way forclass A
to tell what is theID
ofclass B
. This is why when trying to retrieveclass A
it needs to send a query forclass B
to figure out what the ID of class B is, but when it sends the query theclass B
is already loaded so there is no need for it to actualy retrieve it from the cache.When OneToOne will be cached ?
Now if you navigate the opposite way from
class B
toclass A
then you will hit the cache straight away :)Why is @OneToMany(cascade={}, fetch=FetchType.EAGER, mappedBy="a") working ?
In hibernate collections are cached in their dedicated region known as collection cache. Hibernate caches the primary keys of the entities that make up the collection. Not the entities themselves; i.e. there is no Set stored somewhere in the second level cache.
Once the primary key for is retrieved from the collection cache region it falls back to the regular entity cache to retrieve the actual object. Therefore the
@OneToMany
hack works for you.