繁体   English   中英

使用 Hibernate(无 Criteria API)构建动态查询

[英]Build a dynamic query with Hibernate (no Criteria API)

我有以下方法:

public List<Parcel> filter(ParcelFilterParameters pfp) {
    try (var session = sessionFactory.getCurrentSession()) {
        var baseQuery = "from Parcel ";
        var filters = new ArrayList<String>();

        pfp.getCustomerId().ifPresent(e -> filters.add(" owner.id = :ownerId "));
        pfp.getCategoryId().ifPresent(e -> filters.add(" category.id = :categoryId "));


        if (!filters.isEmpty()) {
            baseQuery = baseQuery + " where " + String.join(" and ", filters);
        }

        Query<Parcel> query = session.createQuery(baseQuery, Parcel.class);

        pfp.getCustomerId().ifPresent(e -> query.setParameter("ownerId", e));
        pfp.getCategoryId().ifPresent(e -> query.setParameter("categoryId", e));
        return query.list();
    }
}

这是 ParcelFilterParameters class:

public class ParcelFilterParameters {
    private Optional<Integer> customerId;
    private Optional<Integer> categoryId;

    // getters and setters...
}

虽然看起来很奇怪,但它确实有效,但这对其他一些实体重复,所以我想知道我是否可以以某种方式使其更通用(不使用 Criteria API)? 或者至少跳过第二批ifPresent(e ->... s?

尽管您没有要求使用 Criteria API ,但请考虑使用org.hibernate.criterion.Example 它可以很好地适应越来越多的实体。 该示例自省每个不是 null 的字段,并将从中构建您的where -block。

首先在ParcelFilterParameters中,我们应该从字段中删除Optioals ,因为Example可以很好地处理空值。 然后我们从ParcelFilterParameters构建一个Parcel对象并从中创建一个Example Example可以作为Criterion添加到查询中。

public List<Parcel> filter(ParcelFilterParameters pfp) {
    try (var session = sessionFactory.getCurrentSession()) {
        // Build example Parcel from ParcelFilterParameters
        Parcel parcel = new Parcel();
        // initialize customer/owner and category ...
        parcel.getOwner().setId(pfp.getCustomerId());
        parcel.getCategory().setId(pfp.getCategoryId());

        return session.createCriteria(Parcel.class)
                      .add(Example.create(parcel))
                      .list();
    }
}

为了避免the second batch of ifPresent你可以使用 map 来保存所有查询参数:

List<String> filters = new ArrayList<>();
Map<String, Object> params = new HashMap<>();

pfp.getCustomerId().ifPresent(e -> {
    filters.add(" owner.id = :ownerId ");
    params.put("ownerId", e);
});
pfp.getCategoryId().ifPresent(e -> {
    filters.add(" category.id = :categoryId ");
    params.put("categoryId", e);
});

并在单个方法调用中应用它们:

Query<Parcel> query = session.createQuery(baseQuery, Parcel.class);
query.setProperties(params);
return query.list();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM