2010-07-29 68 views
3

学习如何编写JPA查询。请告诉我是否可以更有效地编写下面的查询,可能在一个select语句中。可能是一个加入,但不知道如何去做。如何编写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返回的组。实际上,我得到了他们所属的人员(客户)与Person(mgr1)具有关系MANAGER的同一组的列表。

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

回答

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'子句在语义上更清楚。

编辑:我addded .id到子选择,我认为是必要的。

+0

谢谢!!工作是完美的(没有ID - 编辑)..会接受的答案,迫不及待地想看到的内层查询的性能是否有人评论是否..这是它的最佳方式..再次感谢.. – bsr 2010-07-29 13:35:14

+0

子查询将很快,因为它不是一个相关的查询 - 它只计算一次,就像您的原始代码一样。就在今天,我用WHERE IN替换了LEFT JOIN,并在SQL服务器上将查询的性能从18秒改为5秒。你不会说你正在使用哪个数据库,但通常情况下,当你只进行存在测试而不使用任何数据时,子查询可以超越联接。 – mdma 2010-07-29 13:42:04

+0

谢谢..计划使用PostgreSQL或Oracle ..我使用休眠ORM,所以可能它可能与其他人兼容..你可以请详细说明存在测试vs不使用任何数据..每天学习新的东西: - )谢谢.. – bsr 2010-07-29 14:24:17

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 

SELECT * FROM Body_Type

ID  NAME 
1  Compact 
2  Convertible 
3  Sedan