3

学习如何编写 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 将他们是 CUSTOMER 的所有人员返回到查询 1 返回的组中。实际上,我得到了他们属于(客户)的人员列表,这些人员与人员(mgr1)有关系的同一组。

是否可以将它们组合成单个 sql 语句,因此可能只有一个 db 访问?

4

2 回答 2

0

您实际上将一个查询嵌套在另一个查询中,并使用“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 添加到子选择中,我认为这是必要的。

于 2010-07-29T13:21:02.203 回答
0

这不是问题的答案,而是帮助其他人,以防有人使用 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
于 2017-12-20T22:38:10.393 回答