Jpa Criteria API,具有@OneTomany关系的动态谓词

时间:2016-05-02 23:35:32

标签: java hibernate jpa criteria-api

以下是我的实体。

TradeItem.class

@Entity
@Table(name = "TRADEITEMS")
public class TradeItem {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "TRADEITEM_ID")
private Long id;

private String shopOwner;

private Boolean corrupted;

private String base;

private String type;

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Mod> mod;

private String league;

...
}

Mod.class

@Entity
@Table(name = "MODS")
public class Mod {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private Double miniValue;

private Double maxiValue;

private String modName;

...

}

DaoImpl

    @Repository
    public class TradeItemDaoImp implements TradeItemDao{

    @PersistenceContext
    private EntityManager em;

    @Override
    public Optional<List<TradeItem>> search(TradeItemRequest request) {
        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<TradeItem> cq = criteriaBuilder.createQuery(TradeItem.class);

        Root<TradeItem> root = cq.from(TradeItem.class);

        List<Predicate> predicates = new LinkedList<>();


        predicates.add(criteriaBuilder.equal(root.get("league"), request.getLeague()));

        if(request.getName() != null){
            predicates.add(criteriaBuilder.like(root.get("name"), "%"+request.getName()+"%"));
        }


        if(request.getType() != null){
            predicates.add(criteriaBuilder.equal(root.get("type"), request.getType()));
        }

        if(request.getBase() != null) {
            predicates.add(criteriaBuilder.equal(root.get("base"), request.getBase()));
        }


        if(request.getIdentified() != null){
            predicates.add(criteriaBuilder.equal(root.get("identified"), request.getIdentified()));
        }

        if(request.getCorrupted() != null){
            predicates.add(criteriaBuilder.equal(root.get("corrupted"), request.getCorrupted()));
        }

        if(request.getMods().size() > 0) {
            Join<TradeItem, Mod> mod = root.joinSet("mod");

            for (ModRequest m : request.getMods()) {

                predicates.add(
                        criteriaBuilder.and(
                            criteriaBuilder.equal(mod.get("modName"), m.getName()),
                            criteriaBuilder.ge(mod.get("miniValue"), m.getMinValue() == null ? 0 : m.getMinValue()),
                            criteriaBuilder.le(mod.get("maxiValue"), m.getMaxValue() == null ? 10000 : m.getMaxValue()))
                );

            }

        }

        cq.select(root)
                .where(predicates.toArray(new Predicate[predicates.size()]));

        TypedQuery<TradeItem> typedQuery = em.createQuery(cq);

        return Optional.of(
                typedQuery
                .setFirstResult(0)
                .setMaxResults(50)
                .getResultList());

    }
}

基本上我在这里要做的就是我为特定的Tradingforum开发了一个Webscraper。我有一个web应用程序,您可以通过表单搜索论坛项目。现在每个TradingItem包含一组mods(@OneToMany),它们具有不同的名称和值。

当我搜索只有一个或零个mod的项目时,它可以正常工作。但是只要我在搜索表单中添加两个或更多个mod,它就会返回一个空列表。

我是Criteria Api的新手,我的mod-predicates / logic显然有问题。

我正在使用hibernate 5.1.0&amp; MySQL的

Example of form

编辑:已解决

我只需将Join移动到for循环中。

        for (ModRequest m : request.getMods()) {

            Join<TradeItem, Mod> mod = root.joinSet("mod");
            predicates.add(
                    criteriaBuilder.and(
                        criteriaBuilder.equal(mod.get("modName"), m.getName()),
                        criteriaBuilder.ge(mod.get("miniValue"), m.getMinValue() == null ? 0 : m.getMinValue()),
                        criteriaBuilder.le(mod.get("maxiValue"), m.getMaxValue() == null ? 10000 : m.getMaxValue()))
            );

        }

0 个答案:

没有答案