Hibernate发布单个查询而不是加入

时间:2016-03-10 21:21:59

标签: java spring hibernate jpa

我有一个应用程序,我正在使用Hibernate和JPA。我有2个对象(订单和产品)。他们加在一起,我可以获得我想要的信息,但它实际发出1个查询来获取我的所有订单,我在我的日志中收到一堆查询以查找产品信息。我尝试了各种注释,但无法使其正常工作。任何帮助都会很棒。

这是我的代码:

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;

import javax.persistence.*;

@Entity
public class ProductFeedback implements ProductFeedbackInterface {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(columnDefinition="INT")
private Long id;
private String decision;
private String reportId;
...
@ManyToOne
@NotFound(action = NotFoundAction.IGNORE)
@JoinColumn(name = "sku", referencedColumnName = "sku", insertable = false, updatable = false)
public Product product;

当我尝试查询此表时,我会得到类似以下查询的信息:

Hibernate: select top 50 productfee0_.id as id1_1_... from product_feedback productfee0_ where 1=1 and productfee0_.date_reported_date>=? and productfee0_.date_reported_date<=? and (productfee0_.decision=? or productfee0_.decision is null) and (productfee0_.dtype=? or productfee0_.dtype=?) and (productfee0_.severity in (0) or productfee0_.dtype<>?) order by productfee0_.date_reported_date desc

Hibernate: select ... from product product0_ where product0_.sku=?
Hibernate: select ... from product product0_ where product0_.sku=?

编辑:::我也试过使用@Fetch(FetchMode.JOIN)也没有运气。

有什么想法吗?

编辑:

我们正在使用规范来构建查询:

public List<ProductFeedback> findAll(ProductFeedbackFilters     productFeedbackFilters) {

    Page recordsPage = jpaRecordRepository.findAll(buildSpecifications(productFeedbackFilters), sortPageable(productFeedbackFilters.getLimit()));
    return recordsPage.getContent();
}

以下是一个示例......

private Specifications<ProductFeedback> defaultSpecifications() {
    return where((queryRoot, query, criteriaBuilder) -> {
        return criteriaBuilder.and(new Predicate[]{}); // Always true
    });
}

private Specification<ProductFeedback> buildSpecifications(ProductFeedbackFilters filters) {
    return new RecordSpecificationsBuilder(filters)
            .onOrAfterStartDate()
            .onOrBeforeEndDate()
            .status()
            .type()
            .userQuery()
            .severity()
            .keyword()
            .build();
}


public ProductFeedback findByReturnIdentifier(Integer catalogNumber, String commentType) {
    return jpaRecordRepository.findOne((queryRoot, query, criteriaBuilder) ->
            criteriaBuilder.and(criteriaBuilder.equal(queryRoot.get("catalogNumber"), catalogNumber), criteriaBuilder.equal(queryRoot.get("commentType"), commentType)));
}

2 个答案:

答案 0 :(得分:2)

您可以告诉持久性提供程序获取与您查询的ProductFeedback.product个实体的Product关系,因此ProductFeedback个对象的简单查询

SELECT pf FROM ProductFeedback pf

会变成

SELECT pf FROM ProductFeedback pf LEFT JOIN FETCH pf.product

使用条件查询,假设您已经有一个Root<ProductFeedback>对象,您可以通过以下方式急切地获取关联的ProductFeedback.product对象:

productFeedbackRoot.fetch("product", JoinType.LEFT);

或者如果你有JPA static metamodel classes generated

productFeedbackRoot.fetch(ProductFeedback_.product, JoinType.LEFT);

答案 1 :(得分:1)

提取策略由hibernate的默认行为决定, 在其文档中解释如 ..

*映射文档中定义的获取策略会影响:

通过get()或load()

进行检索

在导航关联时隐式发生的检索

标准查询

如果使用subselect fetching,则HQL查询 无论您使用何种提取策略,都可以保证将定义的非延迟图加载到内存中。 但是,这可能导致多个立即选择用于执行特定的HQL查询。 通常,映射文档不用于自定义提取。相反,我们保留默认行为,并使用HQL中的左连接提取覆盖特定事务。这告诉Hibernate使用外连接在第一个选择中急切地获取关联。在Criteria查询API中,您将使用setFetchMode(FetchMode.JOIN)。 如果要更改get()或load()使用的提取策略,可以使用Criteria查询。例如:

User user = (User) session.createCriteria(User.class)
            .setFetchMode("permissions", FetchMode.JOIN)
            .add( Restrictions.idEq(userId) )
            .uniqueResult();

这是Hibernate相当于一些ORM解决方案所谓的“获取计划”。*

关键是hibernate希望将获取模式设置为事务级别。