如何使用本机查询在 JPA 中执行嵌套联接
Posted
技术标签:
【中文标题】如何使用本机查询在 JPA 中执行嵌套联接【英文标题】:How to perform nested Join in JPA with native query 【发布时间】: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您需要将连接提取与这样的 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 解决
【讨论】:
以上是关于如何使用本机查询在 JPA 中执行嵌套联接的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Spring Boot JPA 执行具有 INTERVAL 子句的本机 SQL 查询?