复杂搜索查询JPA

Joh*_*nak 10 java annotations criteria-api jpa-2.0

在我的Wicket + JPA/Hibernate + Spring项目中,大部分功能都基于Inbox页面,使用许多过滤选项(并非所有过滤选项都必须使用),用户可以限制他们想要使用的对象集.我想知道实现这种过滤的最佳策略是什么?在此应用程序的旧版本中,搜索查询是连接包含SQL条件的字符串.最近我读到了JPA提供的新Criteria API - 您是否会建议使用搜索字符串?这与DAO层如何结合 - 是不是在业务层中使用Criteria API构建搜索查询是否存在层分离的漏洞?

Adr*_*ter 4

对于像您所描述的过滤查询,我绝对建议使用 Hibernate 或 JPA criteria API,因为它们支持条件查询。我通常只是将标准构造代码放入 DAO 中,并在那里传递所有必需的(可能为空)参数。

以下是使用 Hibernate 标准 API 的示例汽车租赁应用程序中的示例 DAO 方法:

public List<VehicleRentalContract> list(Long contractID,
            String customerNameOrID, Date date,
            String vehicleDescriptionOrRegistration) {
        Criteria criteria = getSession().createCriteria(
                VehicleRentalContract.class);
        // contractID filter
        if (contractID != null && contractID != 0) {
            criteria.add(Restrictions.eq("id", contractID));
        }
        // customerNameOrID filter
        if (customerNameOrID != null && customerNameOrID.length() > 0) {
            try {
                Long customerID = Long.parseLong(customerNameOrID);
                criteria.add(Restrictions.eq("customer.id", customerID));
            } catch (NumberFormatException e) {
                // assume we have a customer name
                String customerNameQuery = "%" + customerNameOrID.trim() + "%";
                criteria.createAlias("customer", "customer").add(
                        Restrictions.or(Restrictions.like("customer.firstName",
                                customerNameQuery), Restrictions.like(
                                "customer.lastName", customerNameQuery)));
            }
        }
        // date filter
        if (date != null) {
            criteria.add(Restrictions.and(
                    Restrictions.le("rentalPeriod.startDate", date),
                    Restrictions.ge("rentalPeriod.endDate", date)));
        }

        // vehicleDescriptionOrRegistration filter
        if (vehicleDescriptionOrRegistration != null
                && vehicleDescriptionOrRegistration.length() > 0) {
            String registrationQuery = "%"
                    + Vehicle
                            .normalizeRegistration(vehicleDescriptionOrRegistration)
                    + "%";
            String descriptionQuery = "%"
                    + vehicleDescriptionOrRegistration.trim() + "%";

            criteria.createAlias("vehicle", "vehicle").add(
                    Restrictions.or(Restrictions.like("vehicle.registration",
                            registrationQuery), Restrictions.like(
                            "vehicle.description", descriptionQuery)));
        }

        List<VehicleRentalContract> contracts = criteria.list();
        return contracts;
}
Run Code Online (Sandbox Code Playgroud)

createAlias 调用可用于需要 SQL 中联接的地方。

  • 可能值得一提的是,这个答案使用 Hibernate Criteria API,而不是 JPA API。 (2认同)