学习如何编写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返回一个组列表,其中person(mgr1)与MANAGER具有关系。查询2将它们所有的客户返回到查询1返回的组。实际上,我得到一个他们所属的人员(客户)列表,其中Person(mgr1)与MANAGER关系相同。
是否可以将它们组合成单个sql语句,因此可能只有一个db访问?
您确实将一个查询嵌套在另一个查询中,并使用“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)
你的调用代码像以前一样传递typeName
,typeName2
和partyFrom
参数。由于数据来自subselect(内部查询),因此不需要PartyTo
参数。
您可以使用自联接实现相同的功能,使用where子句过滤左侧的管理器,使用右侧的客户,但使用“in”子句在语义上更清晰。
编辑:我添加了.id到subselect,我认为是需要的。
这不是问题的答案,但如果有人在使用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