Hibernate 没有在反面缓存我的 OneToOne 关系

发布于 2024-11-08 03:37:25 字数 555 浏览 7 评论 0原文

我的代码如下:

@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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

预谋 2024-11-15 03:37:25

对我有用的解决方法是使用 @OneToMany 创建额外的方法

@OneToMany(cascade={}, fetch=FetchType.EAGER, mappedBy="a")
public Set<B> getBSet() {};

@Transient
public B getB() { return b.iterator().next(); }

,我对此解决方案不太满意,但它有效,而且我找不到其他方法。

Workaround that work for me is create additional method with @OneToMany

@OneToMany(cascade={}, fetch=FetchType.EAGER, mappedBy="a")
public Set<B> getBSet() {};

@Transient
public B getB() { return b.iterator().next(); }

I'm not very happy with this solutions, but it works and I can't find other way.

囍孤女 2024-11-15 03:37:25

尝试将 @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.

故人的歌 2024-11-15 03:37:25

这可能需要更多工作,但您可以尝试使 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

ぽ尐不点ル 2024-11-15 03:37:25

我觉得原来的答案并没有完全解释为什么会发生这种情况。

为什么 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 for class A to tell what is the ID of class B. This is why when trying to retrieve class A it needs to send a query for class B to figure out what the ID of class B is, but when it sends the query the class 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 to class 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文