Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/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
Java Hibernate正在调用saveOrUpdate执行不需要的选择_Java_Hibernate - Fatal编程技术网

Java Hibernate正在调用saveOrUpdate执行不需要的选择

Java Hibernate正在调用saveOrUpdate执行不需要的选择,java,hibernate,Java,Hibernate,假设我有一个房屋实体,它映射到许多个人实体。然后,我加载一个现有的房子,其中有20人 beginTransaction(); House house = houseDao.find(1L); commitTransaction(); 在代码的后面,我可以为房子添加一个新的人: ... List<Person> people = house.getPeople(); people.add(new Person("Dilbert")); .... Hibernate执行21次查询:1

假设我有一个房屋实体,它映射到许多个人实体。然后,我加载一个现有的房子,其中有20人

beginTransaction();
House house = houseDao.find(1L);
commitTransaction();
在代码的后面,我可以为房子添加一个新的人:

...
List<Person> people = house.getPeople();
people.add(new Person("Dilbert"));
....
Hibernate执行21次查询:1次选择房屋,20次选择房屋中的每个现有人员

我相信这对我来说是个小问题,但是,在这种情况下,我应该怎么做才能在不严重影响数据库的情况下为房子添加一个新人呢


所有这些都是在同一个会话中完成的。

因为您对对象的定义没有给出太多的说明,所以我将做一些假设

  • 家对人是一对多
  • 一个人只能属于一所房子
  • 确保房屋的定义如下:

    @Entity
    public class House implements Serializable {
        @Id
        private int id;
    
        @OneToMany(mappedBy="house")
        private Set<Person> people;
    
        ... rest of your class
    }
    
    
    @Entity
    public class Person implements Serializable {
    
        @Id
        private int id;
    
        @ManyToOne(targetEntity=House.class)
        private House house;
    
        @Column(name="person_name")
        private String name
    
        ... rest of your class
    
        public Person(House house, String name) {
           this.house = house;
           this.name = name;
        }
    }
    
    在上面的示例中,当您处理父/子关系时(不管是一对多还是多对多),您可以通过子关系建立关系。我通常不会通过家长进行全面更新。在你的例子中,你会发现这有点过头了。当你开始在有数千条记录的地方工作时,这就变得不可能了

    根据您的模型,另一件需要研究的事情是对列表的注释进行细微的更改。例如:

    @Entity
    public class House implements Serializable {
        @Id
        private int id;
    
        @OneToMany(mappedBy="house")
        @Fetch(FetchMode.JOIN)
        private Set<Person> people;
    
        ... rest of your class
    }
    
    @实体
    公共类房屋实现可序列化{
    @身份证
    私有int-id;
    @OneToMany(mappedBy=“house”)
    @Fetch(FetchMode.JOIN)
    私人设置的人;
    …你们班的其他同学
    }
    
    鉴于@Fetch不是JPA规范的一部分,而是hibernate注释,这取决于您的模型,可以大大提高性能,因为它将在一个查询中绘制房屋对象和所有人。这是非常有效的,如果你是限制数量的房子和人属于房子。如果您得到非常大的结果集,这可能不是一个好情况。下一个示例可能更合适:

    @Entity
    public class House implements Serializable {
        @Id
        private int id;
    
        @OneToMany(mappedBy="house")
        @Fetch(FetchMode.SUBSELECT)
        private Set<Person> people;
    
        ... rest of your class
    }
    
    @实体
    公共类房屋实现可序列化{
    @身份证
    私有int-id;
    @OneToMany(mappedBy=“house”)
    @Fetch(FetchMode.SUBSELECT)
    私人设置的人;
    …你们班的其他同学
    }
    

    这将使用两个查询来获取所有对象。对房屋对象进行一次查询(或根据查询对房屋对象进行乘法),对房屋对象的所有人进行一次查询

    因为您对对象的定义没有给出太多,所以我将做一些假设

  • 家对人是一对多
  • 一个人只能属于一所房子
  • 确保房屋的定义如下:

    @Entity
    public class House implements Serializable {
        @Id
        private int id;
    
        @OneToMany(mappedBy="house")
        private Set<Person> people;
    
        ... rest of your class
    }
    
    
    @Entity
    public class Person implements Serializable {
    
        @Id
        private int id;
    
        @ManyToOne(targetEntity=House.class)
        private House house;
    
        @Column(name="person_name")
        private String name
    
        ... rest of your class
    
        public Person(House house, String name) {
           this.house = house;
           this.name = name;
        }
    }
    
    在上面的示例中,当您处理父/子关系时(不管是一对多还是多对多),您可以通过子关系建立关系。我通常不会通过家长进行全面更新。在你的例子中,你会发现这有点过头了。当你开始在有数千条记录的地方工作时,这就变得不可能了

    根据您的模型,另一件需要研究的事情是对列表的注释进行细微的更改。例如:

    @Entity
    public class House implements Serializable {
        @Id
        private int id;
    
        @OneToMany(mappedBy="house")
        @Fetch(FetchMode.JOIN)
        private Set<Person> people;
    
        ... rest of your class
    }
    
    @实体
    公共类房屋实现可序列化{
    @身份证
    私有int-id;
    @OneToMany(mappedBy=“house”)
    @Fetch(FetchMode.JOIN)
    私人设置的人;
    …你们班的其他同学
    }
    
    鉴于@Fetch不是JPA规范的一部分,而是hibernate注释,这取决于您的模型,可以大大提高性能,因为它将在一个查询中绘制房屋对象和所有人。这是非常有效的,如果你是限制数量的房子和人属于房子。如果您得到非常大的结果集,这可能不是一个好情况。下一个示例可能更合适:

    @Entity
    public class House implements Serializable {
        @Id
        private int id;
    
        @OneToMany(mappedBy="house")
        @Fetch(FetchMode.SUBSELECT)
        private Set<Person> people;
    
        ... rest of your class
    }
    
    @实体
    公共类房屋实现可序列化{
    @身份证
    私有int-id;
    @OneToMany(mappedBy=“house”)
    @Fetch(FetchMode.SUBSELECT)
    私人设置的人;
    …你们班的其他同学
    }
    

    这将使用两个查询来获取所有对象。对房屋对象进行一次查询(或根据查询对房屋对象进行乘法),对房屋对象的所有人进行一次查询

    我认为这是你问题的一个潜在答案,但可能与你的想法不同

    我还没有找到让Hibernate按照您想要的方式运行的方法(它没有那么高的粒度)。如果你愿意,我相信你可以自己编写代码。但是,如果您真的担心数据库的性能会受到影响,请将问题扭转过来,并将重点放在如何最小化数据库的负载上

    优化从Hibernate到DB的调用的最佳方法是确保所有Hibernate对象表都被索引。Hibernate使用父对象的主键调用表。如果这20个查询命中一个索引并被快速定位,那么它们将占用很少的数据库处理时间。DB的构建是为了处理大量类似这样的事务——昂贵的部分是在磁盘上定位数据并加载数据供您使用


    最后,我还要添加一个对象缓存。这可能会消除到数据库的往返,从而为程序节省大量I/O等待时间。

    我认为这是解决您问题的一个可能方法,但可能与您的想法不同

    我还没有找到让Hibernate按照您想要的方式运行的方法(它没有那么高的粒度)。如果你愿意,我相信你可以自己编写代码。但是,如果您真的担心数据库的性能会受到影响,请将问题扭转过来,并将重点放在如何最小化数据库的负载上

    优化从Hibernate到DB的调用的最佳方法是确保所有Hibernate对象表都被索引。Hibernate使用父对象的主键调用表。如果这20个查询命中一个索引并被快速定位,那么它们将占用很少的数据库处理时间。DB'