Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jpa DAO类中的get方法(对于OneToMany)是否总是进行DB调用?_Jpa - Fatal编程技术网

Jpa DAO类中的get方法(对于OneToMany)是否总是进行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”)

假设有两个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”)
    私人援助;
    }
    

    当我检索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;
    
    }