Jpa DAO类中的get方法(对于OneToMany)是否总是进行DB调用?
假设有两个DB表Jpa DAO类中的get方法(对于OneToMany)是否总是进行DB调用?,jpa,Jpa,假设有两个DB表 以主键作为辅助的表A,以及 表B以主键作为投标 @实体 @表(name=“A”) 公共类A实现可序列化{ 私有静态最终长serialVersionUID=1L; @身份证 @列(name=“A_KEY”) 私人援助; @OneToMany(mappedBy=aId) 名单b; } @实体 @表(name=“B”) 公共类B实现可序列化{ 私有静态最终长serialVersionUID=1L; @身份证 @列(name=“B_键”) 私人串投标; @列(name=“A_KEY”)
@实体
@表(name=“A”)
公共类A实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@列(name=“A_KEY”)
私人援助;
@OneToMany(mappedBy=aId)
名单b;
}
@实体
@表(name=“B”)
公共类B实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@列(name=“B_键”)
私人串投标;
@列(name=“A_KEY”)
私人援助;
}
当我检索A时,第一次调用数据库,我有A和关联的B。现在我将A的这个实例保存到某个文件中,并将其读回。当我说(A的实例)#getB时,我不想要DB调用,因为我的内存中有数据。如何避免此DB调用。当您在相同的事务中执行此操作时,多次调用
a#getB()
只会触发一个DB调用,以第一次获取B(因为您在a的B上使用了延迟加载,这是推荐的,而不是将其更改为a)
对a#getB()
的后续调用不会触发任何DB调用。您可以认为在EntityManager
中有一个内存哈希映射(即称为持久性缓存或一级缓存等)。在进行DB调用之前,它将首先尝试检查要加载的实体是否存在于该映射中。如果存在,则从映射返回实体。否则,进行DB调用以获取它,并将加载的实体放入映射中。一级缓存的范围是每个事务,这意味着每个事务都有自己的一级缓存
此外,如果您将文件保存到文件并将其读回。A及其B将不由JPA管理(即处于分离状态),这意味着它不会触发对
A#getB()
的任何DB调用(假设您在从文件读回A后不使用EntityManager
来处理A)。默认情况下,JPA@OneToMany相关实体是惰性地获取的,因此(A的实例)#getB将导致一个DB调用。如果使用fetchType Earge在A中标记B,它将在一次数据库调用中加载整个实体。@S B:谢谢您的回复。您的意思是当它被标记为fetchType Earge,然后(A的实例)#getB调用(在上面解释的场景中)将不会触发DB调用吗?请看我的主要疑问,如果我已经有数据,如何避免DB触发器。这是正确的。在[link]上有一个很好的讨论,基本上-当获取父对象时,急切获取将加载所有子实体,而延迟获取将根据需要加载子实体,即当调用(A的实例)#getB时加载B,而不是加载A时加载B。感谢@Ken Chan,解释得很好。是的,我不使用EntityManager
处理A。一旦我从文件中读取了数据,我就使用A#getB()
来获取关联的B。
@Entity
@Table(name = "A")
public class A implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "A_KEY")
private String aId;
@OneToMany(mappedBy=aId)
List<B> b;
}
@Entity
@Table(name = "B")
public class B implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "B_KEY")
private String bId;
@Column(name = "A_KEY")
private String aId;
}