我的代码如下:
@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
没有缓存,是否可以缓存它?
答案 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
无法分辨ID
中class B
是什么。这就是为什么当尝试检索class A
时,它需要发送一个查询class B
来确定类B的ID是什么,但是当它发送查询时,class B
已经被加载了因此实际上不需要从缓存中检索它。
何时将缓存OneToOne?
现在,如果您从class B
到class A
进行相反的导航,那么您将立即访问缓存:)
@OneToMany(cascade = {},fetch = FetchType.EAGER,mappedBy =“ a”)为什么起作用?
在休眠状态下,集合被缓存在其专用区域(称为集合缓存)中。 Hibernate缓存组成集合的实体的主键。不是实体本身;也就是说,二级缓存中的某个位置没有存储Set。
一旦从集合缓存区域中检索了主键,它就会退回到常规实体缓存中以检索实际对象。因此,@OneToMany
hack非常适合您。
答案 2 :(得分:0)
尝试将@Cache注释放在getB()getter上。我的观察是,如果你缓存对象,它的关联可能不被认为是缓存的。
答案 3 :(得分:0)
这可能需要多做一些工作,但你可以尝试将fetchType设为Lazy,并且 明确地获取B。这样你就可以检查B的实例是否已经加载了?
旁注,你看过这篇文章吗?我认为问题类似: