“where”条件在JPA的连接查询(本地查询)中无法正确工作。

huangapple go评论61阅读模式
英文:

"where" condition not working correctly in join query in JPA (native query)

问题

我正在使用 Spring Boot Starter Web 与 MYSQL 以及 JPA。我已经创建了实体如下:

Parent:

@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;

}

Child:

@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;

}

我为它们各自创建了两个 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。

英文:

I am using Spring Boot Starter Web with MYSQL and JPA. I have created Entities as:

parent:

@Entity
@Table(name = &quot;parent&quot;)
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Parent{

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

   @OneToMany(cascade = CascadeType.ALL)
   @JoinColumn(name = &quot;control_id&quot;, referencedColumnName = &quot;id&quot;)
   private List&lt;Child&gt; childList;

}

Child:

@Entity
@Table(name = &quot;child&quot;)
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Child{

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

}

I have 2 DAOs for both of them as

@EnableJpaRepositories
public interface ParentDao extends JpaRepository&lt;Parent, Long&gt; {
     @Query(value = &quot;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)&quot;, nativeQuery = true)
    Parent findActiveById(@Param(&quot;entry_id&quot;) Long aLong);
}

@EnableJpaRepositories
public interface ChildDao extends JpaRepository&lt;Child, Long&gt; {
      
}

Here what I am trying to achieve is, I want to fetch an Object of Parent with all the Child which are active. but this returns everything, is_active = 1 as well as 0.

答案1

得分: 1

你需要使用join fetch child,而不是join child,这样JPA只会使用一个SQL查询,返回拥有正确子项的父项目。

英文:

You need to use join fetch child instead of join child in order that JPA uses only one SQL Query and returns the parent items having the good child

答案2

得分: 0

你需要返回的是父项,而不是整个连接。按照现在的方式,你的查询返回了一个包含父项和子项连接在一起的集合。

英文:

You need to return only the parent, not the whole join. As it is, your query returns a collection of parent and child joined together.

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)

答案3

得分: 0

你已经有了可以用来获取子项的子存储库。

@EnableJpaRepositories
public interface ChildDao extends JpaRepository<Child, Long> {
      // 这种方式的方法会自动转换为查询语句
      List<Child> findByControl_idAndIs_active(Long control_id, Boolean is_active);
}

// 使用方法如下
List<Child> children = childDao.findByControl_idAndIs_active(control_id, true); 

// 然后单独获取父项,或者也可以在之前获取
Optional<Parent> parent = parentDao.findById(parent_id);

如果你想知道这些方法是从哪里来的,请参阅这个链接

但如果你想要在同一个查询中获取父项和子项,并且作为同一结构返回,那是不可能的。你可以使用自定义查询将结果获取到一个带有所需字段的 Dto 列表中,然后在代码中创建父子结构。

一个建议是,在 Java 中应该使用驼峰命名法,例如使用 controlId 替代 control_id,并使用 @Column(name='control_id'),不过这是你的选择 “where”条件在JPA的连接查询(本地查询)中无法正确工作。

英文:

You already have child repository which you can use to fetch children

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

// Use it like this
List&lt;Child&gt; children = childDao.findByControl_idAndIs_active(control_id, true); 

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

If you are wondering from where these methods came then please See This

But if you want to fetch parent and child both in one query as a same structure then it wouldn't be possible, one thing you can do is fetch using custom query into a List of Dto with required fields and then create parent-child like structure in your code.

One suggestion, you should name variable in camel case in java i.e controlId instead of control_id and use @column(name=&#39;control_id&#39;) but its your choice “where”条件在JPA的连接查询(本地查询)中无法正确工作。

huangapple
  • 本文由 发表于 2020年9月11日 21:04:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/63847675.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定