Java 如何编写JPA查询
学习如何编写JPA查询。请告知我是否可以在单个select语句中更有效地编写以下查询。可能是加入,但不确定如何加入Java 如何编写JPA查询,java,jpa,orm,jpql,Java,Jpa,Orm,Jpql,学习如何编写JPA查询。请告知我是否可以在单个select语句中更有效地编写以下查询。可能是加入,但不确定如何加入 class Relationship { @ManyToOne public String relationshipType; //can be MANAGER, CUSTOMER etc @ManyToOne public Party partyFrom; // a person who has a relation @ManyToOne publ
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返回一个组列表,其中personmgr1有一个与的关系管理器。查询2将他们是客户的所有人员返回到查询1返回的组。实际上,我得到了一个他们属于客户组的人员列表,该客户组中的人员mgr1有一个关系经理
是否可以将它们组合到一个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和Party。不需要PartyTo参数,因为数据来自子SELECT内部查询
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)
使用自连接可以实现同样的效果,其中where子句在左侧过滤经理,在右侧过滤客户,但使用“in”子句在语义上更清晰
编辑:我在子选择中添加了.id,我认为这是必需的。这不是对问题的回答,而是帮助其他人,以防有人使用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);
从Body_Type中选择*
ID NAME
1 Compact
2 Convertible
3 Sedan
谢谢在没有id的情况下工作完美-编辑。。将接受答案,等待查看是否有人对内部查询的性能发表评论。。这是否是实现这一目标的最佳方式。。再次感谢..子查询会很快,因为它不是一个相关查询-它只计算一次,就像原始代码一样。就在今天,我用WHERE-IN替换了一个左连接,并将SQL server上的查询性能从18秒改为5秒。您不会说您使用的是哪一个数据库,但一般来说,当您只进行存在性测试而不使用任何数据时,子查询的性能会优于联接。谢谢。。计划使用PostgreSQL或Oracle。。我使用hibernate ORM,因此它也可能与其他ORM兼容。。你能详细说明一个生存测试与不使用任何数据的情况吗。。每天学习新内容:-谢谢..使用联接,通常这样做是为了从联接表中引入其他字段。有些人还使用外部联接作为一种存在性测试—该键是否存在于联接值集中。但是,由于联接表中不需要任何其他字段,因此使用WHERE IN子句效率更高。