假设有两个数据库表,例如
@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;
}
[当我检索A时,第一次调用数据库,并且我拥有A和关联的B。现在,我将此A实例保存到某个文件中并读回。当我说(A的实例)#getB时,我不想进行数据库调用,因为我将数据存储在内存中。如何避免此数据库调用。
(当您在same事务中执行此操作时,多次调用a#getB()
仅会首次触发数据库调用来获取B ((因为您正在对A的B使用延迟加载,推荐设置,而不是将其更改为code smell的Eager。
a#getB()
上的后续调用将不会触发任何数据库调用。您可以认为实体管理器内部有一个内存中的哈希映射(即,称为持久性缓存或一级缓存等)。它将首先尝试在进行数据库调用之前检查要加载的实体在此映射中是否存在。如果存在,则从地图返回实体。否则,请进行数据库调用以获取它,并将加载的实体放入地图中。 1级缓存的范围是每个事务,这意味着每个事务都将拥有自己的1级缓存。
[另外,如果您将A保存到文件并读回。 A和它的B将不受JPA管理(即处于分离状态),并且将不会触发a#getB()
上的任何数据库调用(假设您从文件读回它之后不使用EntityManager处理A)。