【问题标题】:Spring Data @OneToMany(fetch=FetchType.EAGER) working as select query modeSpring Data @OneToMany(fetch=FetchType.EAGER) 用作选择查询模式
【发布时间】:2020-07-14 02:11:52
【问题描述】:

我附在我的代码下方。当我得到所有父实体时,一个一个地加载孩子。如何解决?

父实体类。它具有 3 个属性,即 id、name 和 children。孩子属性加载急切。因为我需要父对象及其子对象。

    @Entity
    @Table(name = "parent")
    public class Parent {
        @Id
        private int id;

        private String name;

        @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.EAGER, orphanRemoval = true)
        private List<Child> children;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public List<Child> getChildren() {
            return children;
        }

        public void setChildren(List<Child> children) {
            this.children = children;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

儿童班。它具有 3 个属性,例如 id、name 和 parent。父属性加载为惰性模式。因为我从不想要子对象和它的父对象。

    @Entity
    @Table(name = "child")
    public class Child {
        @Id
        private int id;

        @Column(name = "name")
        private String name;

        @JsonIgnore
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "parent", referencedColumnName = "id")
        private Parent parent;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Parent getParent() {
            return parent;
        }

        public void setParent(Parent parent) {
            this.parent = parent;
        }
    }

我尝试让所有父母使用以下代码。

    protected List getAll(){
            EntityManager entityManager = entityManagerFactory.createEntityManager();
            entityManager.getTransaction().begin();
            List<Parent> objects = entityManager.createQuery("Select o from Parent o", Parent.class).getResultList();
            entityManager.getTransaction().commit();
            entityManager.close();
            return objects;
        }

我希望只有一个连接查询。但是hibernate调用会一一查询。它得到 n+1 查询问题。

    Hibernate: select parent0_.id as id1_8_, parent0_.name as name2_8_ from parent parent0_
    Hibernate: select children0_.parent as parent3_0_0_, children0_.id as id1_0_0_, children0_.id as id1_0_1_, children0_.name as name2_0_1_, children0_.parent as parent3_0_1_ from child children0_ where children0_.parent=?
    Hibernate: select children0_.parent as parent3_0_0_, children0_.id as id1_0_0_, children0_.id as id1_0_1_, children0_.name as name2_0_1_, children0_.parent as parent3_0_1_ from child children0_ where children0_.parent=?
    Hibernate: select children0_.parent as parent3_0_0_, children0_.id as id1_0_0_, children0_.id as id1_0_1_, children0_.name as name2_0_1_, children0_.parent as parent3_0_1_ from child children0_ where children0_.parent=?

【问题讨论】:

标签: hibernate spring-data-jpa spring-data


【解决方案1】:

JPA 没有提供任何关于映射注解以选择获取策略的规范。

使用JOIN FETCH 在一个查询中获取根实体及其映射的实体/集合,从而解决了 N+1 查询问题。喜欢

SELECT distinct p FROM Parent p LEFT JOIN FETCH p.children

【讨论】:

  • 您的查询作为单个查询工作。但它返回重复值。其实我想知道为什么这种情况不能通过休眠自动管理?
  • 我使用 distinct 关键字删除重复值。现在它工作正常。
  • JPA 没有提供任何关于映射注释以选择获取策略的规范。抱歉,更新我的答案时错误地删除了distinct。 (见我的编辑故事:P)
  • @Niroshan 你明白了吗? join 从连接的表中创建行的笛卡尔积。
猜你喜欢
  • 1970-01-01
  • 2018-04-03
  • 2014-11-17
  • 2016-11-10
  • 2017-08-14
  • 2015-01-30
  • 1970-01-01
  • 2022-08-14
  • 2014-08-08
相关资源
最近更新 更多