【问题标题】:How to perform nested Join in JPA with native query如何使用本机查询在 JPA 中执行嵌套联接
【发布时间】:2021-02-23 08:04:29
【问题描述】:

我有这个结构的现有表学生、额外人员和地址

Table student
------------------------------------------
id  |   name    
------------------------------------------
1   | John          
------------------------------------------

Table extras
-----------------------------------------------------------------
id  |   student_id  |  extras_key               | extras_value
-----------------------------------------------------------------
1   | 1             | class                     | X3
2   | 1             | address_id                | addr-2
-----------------------------------------------------------------

Table address
--------------------------------------------
addr_id     |   name            | city
--------------------------------------------
addr-2      | Office            | San Jose
--------------------------------------------

如何在 JPA Hibernate 上加入这些表?我当前的代码是

学生实体课

@Entity
@Table(name = "student")
@Data
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "name", nullable = false, columnDefinition = "TEXT")
    private String name;

//    @OneToOne
//    @JoinColumn(name = "id", referencedColumnName = "student_id")
//    private Extras extras;

    @OneToMany(mappedBy = "studentId")
    private Set<Extras> extras;
}

附加实体类:

@Data
@Entity
@Table(name="extras")
public class Extras implements Serializable {
    @Id
    @Column(name="id")
    private int id;

    @Column(name="student_id", nullable = false)
    private int studentId;

    @Column(name="extras_key", nullable = false)
    private String extrasKey;

    @Column(name="extras_value", nullable = false)
    private String extrasValue;

    @OneToOne(optional = false)
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "extras_value", referencedColumnName = "addr_id", insertable = false, updatable = false)
    private Address address;
}

和地址实体类

@Entity
@Table(name="address")
@Data
public class Address implements Serializable {
    @Id
    @Column(name="addr_id")
    private String addrId;

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

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

}

这是我的存储库类

@Repository
public interface StudentRepository extends CrudRepository<Student, Integer> {
    @Query(value = "select * from student " +
            "JOIN extras ON student.id=extras.student_id " +
            "JOIN address ON address.addr_id = extras.extras_value", nativeQuery = true)
    List<Student> findAllData();
}

但是当我在学生实体中使用 OneToMany 时,出现异常 "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.jpa.belajarjpa.enitities.Student.extras, could not initialize proxy - 没有会话”。但是当我在 Student Entity 中使用 OneToOne 时,我没有遇到异常但得到了错误的结果,Student(id=1, name=john, extras=null),当我执行这个查询时,它显示了正确的结果 SELECT * FROM student JOIN extras ON student.id=extras.student_id JOIN address ON address.addr_id = extras.extras_value

【问题讨论】:

  • Extras 是 OneToOne 但在数据库中你有两个条目。这是正确的吗?
  • 是的,实际上它是 OneToMany,但是当我尝试使用 @OneToMany 和 Set 作为结果类型时,它会抛出错误。这是我在 @OneToMany(mappedBy = "student", fetch = FetchType.LAZY) Set extras; 之前的代码
  • 我已经编辑了使用 OneToMany 关系的代码,但仍然出现一些错误

标签: java spring-boot hibernate jpa


【解决方案1】:

您需要将连接提取与这样的 HQL 查询一起使用:

@Repository
public interface StudentRepository extends CrudRepository<Student, Integer> {
    @Query("FROM Student s " +
            "JOIN FETCH s.extras e " +
            "JOIN FETCH e.address")
    List<Student> findAllData();
}

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true 是一种反模式。如果我是你,我不会使用它。

【讨论】:

  • 谢谢!我编辑到 @Query("from Student s JOIN FETCH s.extras e JOIN FETCH e.address");
  • 使用本机查询提出的问题。由于 multiplebagfetchexception,我无法使用 HQL
  • 那么不要使用List,而是使用Set 作为您的收藏。应禁止使用List IMO。该类型附带的语义太可怕了。
【解决方案2】:

通过在属性中添加 spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true 解决

【讨论】:

    猜你喜欢
    • 2013-09-18
    • 2021-01-11
    • 1970-01-01
    • 2021-01-08
    • 2016-03-13
    • 2021-06-04
    • 1970-01-01
    • 2015-06-16
    • 2017-08-23
    相关资源
    最近更新 更多