在我的Wicket + JPA / Hibernate + Spring项目中,大部分功能都基于Inbox页面,使用许多过滤选项(并非所有过滤选项都必须使用),用户可以限制他们想要的对象集跟...共事。我想知道实现这种过滤的最佳策略是什么?在此应用程序的旧版本中,搜索查询是连接包含SQL条件的字符串。最近我读到了JPA提供的新Criteria API - 您是否会建议使用搜索字符串?这与DAO层如何结合 - 是不是在业务层中使用Criteria API构建搜索查询是否存在层分离的漏洞?
答案 0 :(得分:4)
对于过滤您所描述的查询,我绝对建议使用Hibernate或JPA条件API,因为它支持条件查询。我通常只是将标准构造代码放在我的DAO中并在那里传递所有必需的(可能为null)参数。
以下是使用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;
}
createAlias调用可以在需要SQL连接的地方使用。
答案 1 :(得分:1)
即使我更喜欢使用Criteria而不是HQL和SQL,因为我的理由是模块化和性能,因为当项目投入生产时,我们面临的主要问题是性能,HQL和SQL都无法竞争Criteria而不是性能。
添加到上面创建DAO层用于访问数据,并且该层应该像玻璃一样清晰,没有任何复杂的编码或业务逻辑,但是在标准的情况下,必须编写逻辑(创建标准)到以更好和更好的方式访问对象,所以在我看来,将这么多逻辑放在DAO层中并没有违反。
答案 2 :(得分:1)
两种方法:
1 ..根据您需要的过滤方式,您可以通过搜索以下内容来实现此目的。使用Lucene索引所有对象,然后使用搜索查询来执行过滤。例如,建立一个像:
的查询标题:“正确的方式”&amp; mod_date:[20020101 TO 20030101]
请参阅:http://lucene.apache.org/java/2_4_0/queryparsersyntax.html
2 ..或使用标准......
我将使用来自hibernate的新的类型安全标准api:
我尝试使用分离标准分离出所有逻辑,而不是一种构建非常大的标准的方法 -
通过这两者的组合,您可以轻松地建立标准。
另一个寻找灵感的地方是grails动态查找器。这基本上是你想要以静态方式实现的目标。
http://www.grails.org/doc/1.0.x/guide/single.html#5.4.1动态查找器
如果你真的想要完全分离图层,你可以实现一个简单的语法。然后解析它以创建相关标准。这将允许更改基础标准实现。这是否合适取决于这种抽象对你的重要性。