jpql join,where子句有意想不到的效果

时间:2012-01-01 19:40:41

标签: hibernate jpa jpql

使用hibernate我有以下查询

    String PQ = "select k from Customer k inner join k.winterSet vs where vs.year = :year";
    TypedQuery<Customer> tq = legacyEm.createQuery(PQ,Customer.class);
    tq.setParameter("year", DateUtil.getCurrentWinterSeason());
    List<Customer> result = tq.getResultList();

客户中的映射

@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
private Set<Winter> winterSet = new HashSet<>(0);

和冬天

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cnr")
private Customer customer;

当我运行此查询时,我只从Customer获得实际在Winter中具有相关行的行,其中属性year与给定参数匹配。到现在为止还挺好。但是,这些Customer对象的winterSet填充了所有相关的Winter对象,而不仅仅是那些在year属性中具有所需值的对象。我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:0)

这是完全正常和预期的结果。使用映射,您可以定义实体的结构,包括与其他实体的关系。查询定义了这些实体中的哪些实体。

使用FetchType,您可以部分控制是否获取查询实体的某些持久属性。但是没有机制只填充集合的某些元素。

如果您需要的结果只显示实体中的部分数据,那么您可以创建呈现部分结果的新类,并使用查询和构造函数表达式填充它。

答案 1 :(得分:0)

加入fetch可以解决问题:

字符串PQ =“从客户k内连接FETCH k.winterSet vs中选择k,其中vs.year =:year”;

调试hibernate表示生成的sql包含where子句。但是,由于关系映射为LAZY,因此不会从此查询中填充集合,只会填充Customer对象。稍后访问集合时,会触发加载,但此时,are子句早已消失,并且所有对象都已加载。

但是,当使用“join fetch”(实际上一次从查询中加载所有对象)时,hibernate会从查询的结果集中填充所有内容,因此只有所需的对象出现在集合中。这样做更有效率,只执行了一个查询,之后不需要加载集合中的每个对象,只是为了抛弃大部分对象。

编辑:仅适用于休眠状态,如果修改了结果,可能会产生严重的副作用。见评论。