用于mappedBy对象的Hibernate缓存

时间:2011-05-20 06:44:32

标签: java hibernate caching jpa one-to-one

我的代码如下:

@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.getB()A没有缓存,是否可以缓存它?

4 个答案:

答案 0 :(得分:2)

对我有用的解决方法是使用@OneToMany

创建其他方法
@OneToMany(cascade={}, fetch=FetchType.EAGER, mappedBy="a")
public Set<B> getBSet() {};

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

我对这个解决方案不是很满意,但它有效,我找不到其他方法。

答案 1 :(得分:1)

我认为原始答案并没有完全涵盖为什么发生这种情况。

为什么不缓存OneToOne?

由于class A不是该关系的所有者,并且在其表内不包含@JoinColumn,因此未缓存它。因此,class A无法分辨IDclass B是什么。这就是为什么当尝试检索class A时,它需要发送一个查询class B来确定类B的ID是什么,但是当它发送查询时,class B已经被加载了因此实际上不需要从缓存中检索它。

何时将缓存OneToOne?

现在,如果您从class Bclass A进行相反的导航,那么您将立即访问缓存:)

@OneToMany(cascade = {},fetch = FetchType.EAGER,mappedBy =“ a”)为什么起作用?

在休眠状态下,集合被缓存在其专用区域(称为集合缓存)中。 Hibernate缓存组成集合的实体的主键。不是实体本身;也就是说,二级缓存中的某个位置没有存储Set。

一旦从集合缓存区域中检索了主键,它就会退回到常规实体缓存中以检索实际对象。因此,@OneToMany hack非常适合您。

答案 2 :(得分:0)

尝试将@Cache注释放在getB()getter上。我的观察是,如果你缓存对象,它的关联可能不被认为是缓存的。

答案 3 :(得分:0)

这可能需要多做一些工作,但你可以尝试将fetchType设为Lazy,并且 明确地获取B。这样你就可以检查B的实例是否已经加载了?

旁注,你看过这篇文章吗?我认为问题类似:

https://forum.hibernate.org/viewtopic.php?p=2378461