如何编写JPA查询

发布于 2024-09-12 04:01:26 字数 1422 浏览 6 评论 0原文

学习如何编写 JPA 查询。请告诉我是否可以更有效地编写以下查询,可以在单个选择语句中。可能是加入,但不知道如何去做。

class Relationship {

  @ManyToOne
  public String relationshipType;  //can be MANAGER, CUSTOMER etc

  @ManyToOne
  public Party partyFrom; // a person who has a relation

  @ManyToOne
  public Party partyTo; // a group a person relate to
}

查询:

        String sql = "";
        sql = "select rel.partyTo";
        sql += " from Relationship rel";
        sql += " where rel.partyFrom = :partyFrom";
        sql += " and rel.relationshipType= :typeName";
        Query query = Organization.em().createQuery(sql);
        query.setParameter("partyFrom", mgr1);
        query.setParameter("typeName", "MANAGER");
        List<Party> orgList = query.getResultList();

        String sql2 = "";
        sql2 = "select rel.partyFrom";
        sql2 += " from Relationship rel";
        sql2 += " where rel.partyTo = :partyToList";
        sql2 += " and rel.relationshipType = :typeName2";
        Query query2 = Organization.em().createQuery(sql2);
        query2.setParameter("partyToList", orgList);
        query2.setParameter("typeName2", "CUSTOMER");
        List<Party> personList2 = query2.getResultList();

这两个查询都有效。查询 1 返回组列表,其中人员 (mgr1) 与其具有关系 MANAGER。查询 2 返回他们属于查询 1 返回的组的所有客户。实际上,我得到了他们所属的人员(客户)的列表,该人员与人员 (mgr1) 具有关系为 MANAGER。

是否可以将它们组合成单个 sql 语句,这样可能只有一个数据库访问?

Learning how to write JPA query. Please advise me whether it possible to write the below queries more efficiently, may be in a single select statement. May be a join, but not sure how to do it.

class Relationship {

  @ManyToOne
  public String relationshipType;  //can be MANAGER, CUSTOMER etc

  @ManyToOne
  public Party partyFrom; // a person who has a relation

  @ManyToOne
  public Party partyTo; // a group a person relate to
}

Queries:

        String sql = "";
        sql = "select rel.partyTo";
        sql += " from Relationship rel";
        sql += " where rel.partyFrom = :partyFrom";
        sql += " and rel.relationshipType= :typeName";
        Query query = Organization.em().createQuery(sql);
        query.setParameter("partyFrom", mgr1);
        query.setParameter("typeName", "MANAGER");
        List<Party> orgList = query.getResultList();

        String sql2 = "";
        sql2 = "select rel.partyFrom";
        sql2 += " from Relationship rel";
        sql2 += " where rel.partyTo = :partyToList";
        sql2 += " and rel.relationshipType = :typeName2";
        Query query2 = Organization.em().createQuery(sql2);
        query2.setParameter("partyToList", orgList);
        query2.setParameter("typeName2", "CUSTOMER");
        List<Party> personList2 = query2.getResultList();

Both the queries work. Query 1 returns a list of groups, where the person (mgr1) has a relation MANAGER with. Query 2 returns all the Persons they are CUSTOMER to the groups returned by query 1. In effect, I get a list of Person they are belong to (customer) the same group where the Person (mgr1) has a relation MANAGER with.

Is it possible to combine them into single sql statement so possibly only one db access?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

在巴黎塔顶看东京樱花 2024-09-19 04:01:26

您可以将一个查询嵌套在另一个查询中,并使用“where in”子句指定外部查询应从内部查询中获取客户。

select rel2.partyFrom
from Relationship rel2
where rel2.relationshipType = :typeName2 /* customer */
and rel2.partyTo.id in 
      (select rel.partyTo.id
      from Relationship rel
      where rel.partyFrom = :partyFrom
      and rel.relationshipType = :typeName)

您的调用代码像以前一样传递 typeNametypeName2partyFrom 参数。不需要 PartyTo 参数,因为数据来自子选择(内部查询)。

您可以使用自联接实现相同的效果,并使用 where 子句过滤左侧的经理和客户在右侧,但使用“in”子句在语义上更清晰。

编辑:我将 .id 添加到子选择中,我认为这是需要的。

You literally nest one query inside the other, and use a "where in" clause to specify that the outer query should fetch customers from the inner query.

select rel2.partyFrom
from Relationship rel2
where rel2.relationshipType = :typeName2 /* customer */
and rel2.partyTo.id in 
      (select rel.partyTo.id
      from Relationship rel
      where rel.partyFrom = :partyFrom
      and rel.relationshipType = :typeName)

Your calling code passes typeName, typeName2, and partyFrom parameters as before. PartyTo parameter is not needed, since the data comes from the subselect (inner query.)

You can achieve the same thing using a self join, with a where clause that filters managers on the left side, and customers on the right side, but using an 'in' clause is semantically clearer.

EDIT: I addded .id to the subselect, which I think is needed.

朱染 2024-09-19 04:01:26

这不是问题的答案,而是帮助其他人,以防有人使用 JPQL 在 Spring Data JPA 中查找 @OneToMany 关系,因为这个问题与 JPA 相关,所以想分享我的 2 美分,提前道歉

@Entity
@Table(name = "MY_CAR")
public class MyCar {

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

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

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

@Column(name = "RELEASE_DATE")
private Date releaseDate;

@OneToMany(cascade = { CascadeType.ALL })
@JoinTable(name = "MY_CAR_VEHICLE_SERIES", joinColumns = @JoinColumn(name = "MY_CAR_ID "), inverseJoinColumns = @JoinColumn(name = "VEHICLE_SERIES_ID"))
private Set<VehicleSeries> vehicleSeries;
public MyCar() {
    super();
    vehicleSeries = new HashSet<VehicleSeries>();
}
// set and get method goes here


@Entity
@Table(name = "VEHICLE_SERIES ")
public class VehicleSeries {

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

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

@OneToMany(cascade = { CascadeType.ALL })
@JoinTable(name = "VEHICLE_SERIES_BODY_TYPE", joinColumns = @JoinColumn(name = "VEHICLE_SERIES_ID"), inverseJoinColumns = @JoinColumn(name = "BODY_TYPE_ID"))
private Set<BodyType> bodyTypes;
public VehicleSeries() {
    super();
    bodyTypes = new HashSet<BodyType>();
}
// set and get method goes here


@Entity
@Table(name = "BODY_TYPE ")
public class BodyType implements Serializable {

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

@Column(name = "NAME")
private String name;
// set and get method goes here


public interface MyCarRepository extends JpaRepository<MyCar, Long> {
public Set<MyCar> findAllByOrderByIdAsc();

@Query(value = "select distinct myCar from MyCar myCar "
        + "join myCar.vehicleSeries as vs join vs.bodyTypes as bt where vs.seriesNumber like %:searchMyCar% "
        + "or lower(bt.name) like lower(:searchMyCar) or myCar.bulletinId like %:searchMyCar% "
        + "or lower(myCar.description) like lower(:searchMyCar) "
        + "or myCar.bulletinNumber like %:searchMyCar% order by myCar.id asc")
public Set<MyCar> searchByMyCar(@Param("searchMyCar") String searchMyCar);

}

表中的一些数据就像

从 Vehicle_Series 选择 *

ID      SERIES_NUMBER  
1       Yaris
2       Corolla

从 Body_Type 选择 *

ID      NAME  
1       Compact
2       Convertible 
3       Sedan

This is not answer to question but helping other folks in case if someone looking into @OneToMany relation in Spring Data JPA using JPQL, because the question is related to JPA so thought to share my 2-cents, apologize in advance

@Entity
@Table(name = "MY_CAR")
public class MyCar {

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

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

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

@Column(name = "RELEASE_DATE")
private Date releaseDate;

@OneToMany(cascade = { CascadeType.ALL })
@JoinTable(name = "MY_CAR_VEHICLE_SERIES", joinColumns = @JoinColumn(name = "MY_CAR_ID "), inverseJoinColumns = @JoinColumn(name = "VEHICLE_SERIES_ID"))
private Set<VehicleSeries> vehicleSeries;
public MyCar() {
    super();
    vehicleSeries = new HashSet<VehicleSeries>();
}
// set and get method goes here


@Entity
@Table(name = "VEHICLE_SERIES ")
public class VehicleSeries {

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

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

@OneToMany(cascade = { CascadeType.ALL })
@JoinTable(name = "VEHICLE_SERIES_BODY_TYPE", joinColumns = @JoinColumn(name = "VEHICLE_SERIES_ID"), inverseJoinColumns = @JoinColumn(name = "BODY_TYPE_ID"))
private Set<BodyType> bodyTypes;
public VehicleSeries() {
    super();
    bodyTypes = new HashSet<BodyType>();
}
// set and get method goes here


@Entity
@Table(name = "BODY_TYPE ")
public class BodyType implements Serializable {

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

@Column(name = "NAME")
private String name;
// set and get method goes here


public interface MyCarRepository extends JpaRepository<MyCar, Long> {
public Set<MyCar> findAllByOrderByIdAsc();

@Query(value = "select distinct myCar from MyCar myCar "
        + "join myCar.vehicleSeries as vs join vs.bodyTypes as bt where vs.seriesNumber like %:searchMyCar% "
        + "or lower(bt.name) like lower(:searchMyCar) or myCar.bulletinId like %:searchMyCar% "
        + "or lower(myCar.description) like lower(:searchMyCar) "
        + "or myCar.bulletinNumber like %:searchMyCar% order by myCar.id asc")
public Set<MyCar> searchByMyCar(@Param("searchMyCar") String searchMyCar);

}

Some data in tables like

Select * from Vehicle_Series

ID      SERIES_NUMBER  
1       Yaris
2       Corolla

Select * from Body_Type

ID      NAME  
1       Compact
2       Convertible 
3       Sedan
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文