“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_id
和is_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]