“where”条件在 JPA 中的联接查询中无法正常工作(本机查询)

Posted

技术标签:

【中文标题】“where”条件在 JPA 中的联接查询中无法正常工作(本机查询)【英文标题】:"where" condition not working correctly in join query in JPA (native query) 【发布时间】:2020-09-11 13:04:53 【问题描述】:

我正在使用带有 mysql 和 JPA 的 Spring Boot Starter Web。我将实体创建为:

父母:

@Entity
@Table(name = "parent")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Parent

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Long id;

   @OneToMany(cascade = CascadeType.ALL)
   @JoinColumn(name = "control_id", referencedColumnName = "id")
   private List<Child> childList;


孩子:

@Entity
@Table(name = "child")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Child

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Long id;
   private Long control_id;
   private Boolean is_active;


我有 2 个 DAO 用于他们两个

@EnableJpaRepositories
public interface ParentDao extends JpaRepository<Parent, Long> 
     @Query(value = "SELECT * FROM parent as p inner join child as c on p.id = c.control_id WHERE (c.is_active = 1 and p.id = :entry_id)", nativeQuery = true)
    Parent findActiveById(@Param("entry_id") Long aLong);


@EnableJpaRepositories
public interface ChildDao extends JpaRepository<Child, Long> 
      

我想要实现的是,我想获取一个父对象,其中包含所有活动的子对象。但这会返回所有内容,is_active = 1 和 0。

【问题讨论】:

你不能这样做,如果你只需要活跃的孩子,使用ChildDao使用control_idis_active单独获取,然后单独获取父并编写你的逻辑。 你能推荐一下方法吗? 【参考方案1】:

您已经有可以用来获取孩子的子存储库

@EnableJpaRepositories
public interface ChildDao extends JpaRepository<Child, Long> 
      // Method in this manner will be automatically converted into a query
      List<Child> findByControl_idAndIs_active(Long control_id, Boolean is_active);


// Use it like this
List<Child> children = childDao.findByControl_idAndIs_active(control_id, true); 

// Then fetch the Parent separately or can fetch before also
Optional<Parent> parent = parentDao.findById(parent_id);

如果您想知道这些方法的来源,请See This

但是,如果您想在一个查询中将父项和子项都作为同一个结构获取,那么这是不可能的,您可以做的一件事是使用自定义查询将其提取到具有必填字段的 Dto 列表中,然后创建父项- 代码中的子类结构。

一个建议,您应该在 java 中以驼峰式命名变量,即 controlId 而不是 control_id 并使用 @column(name='control_id'),但这是您的选择:)

【讨论】:

所以你的意思是我应该先获取子列表,然后将其设置为父对象?如果是这样的话,当我们调用 parentDao.findById(id);它获取所有使 api 非常慢的数据,因为将有超过 1000 个不活动的孩子。我该如何阻止它,以便它只会获取没有子列表的父对象?? 在我的回答中,我建议在单独的调用中获取children,而不是使用parent,我已经包含了父母的想法,即您可能需要来自父对象的一些信息才能包含在您的逻辑中。你还没有给出你想要做的整个用例,如果你只想获取活动的孩子,然后使用ChildDao的条件获取它们,如果你想在一个查询中同时包含父母和孩子,你需要自定义查询, AFAIK,它不能按照您的想法完成。【参考方案2】:

您只需要返回父节点,而不是整个连接。实际上,您的查询会返回一个父子节点的集合。

SELECT p FROM parent p inner join child c on p.id = c.control_id WHERE (c.is_active = 1 and p.id = :entry_id)

【讨论】:

它返回 2020-09-11 19:52:49.851 错误 12876 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper:未知列 'p' in '字段列表' 因为它是你想要的原生查询SELECT p.* FROM ...

以上是关于“where”条件在 JPA 中的联接查询中无法正常工作(本机查询)的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询条件放在LEFT OUTER JOIN 的ON语句后与放在WHERE中的区别

如何根据postgres的jsonb列的where条件(无本机查询)使用jpa在spring boot中选择数据?

JPA Criteria API where subclass - 出现错误:无法针对路径 [null] 解析属性 [lastName]

如何使用本机查询在 JPA 中执行嵌套联接

JPA标准WHERE子句

JPA 中的条件 where 子句