【发布时间】:2014-08-20 16:17:59
【问题描述】:
在我的示例中,我只使用我的实体对象“合同”创建了一个 Hibernate 标准。
@Transactional
public static List<Contract> findAllContractsPerContract(Contract contract) {
EntityManager e = entityManager().getEntityManagerFactory().createEntityManager();
Session session = e.unwrap(Session.class);
Example contractExample = Example.create(contract).excludeProperty("fromDate").excludeProperty("endDate");;
Criteria c = session.createCriteria(Contract.class).add(contractExample);
// here some restriction can be done. (in a dynamic way like equlas/greater/less...)
List<Contract> list = c.list();
return list;
}
合约对象有很多参数。在这种情况下,合约的所有参数都通过 equals 搜索。所以,如果参数匹配,我会得到正确的结果。
但现在我想为合约对象的一些参数添加一些标准。例如两个参数是:“fromDate”和“endDate”。可以修改现有标准,例如 >= fromDate 和 (或介于两者之间)。标准也应该是动态的。
我知道我可以在这一行的末尾添加一些标准:
Criteria c = session.createCriteria(Contract.class).add(contractExample);
但这只是对现有查询的补充。 是否有解决方案或其他技术方法来解决问题?
感谢您的意见。
更新 1
没有操作数的请求:
allRequestParams={"v00Datvon":"09-07-2014","v00Datbis":"09-07-2014","v00Saicode":{"saiCode":"SO02"}}
带有操作数的请求示例
allRequestParams={"v00Datvon":"09-07-2014","operand":"less","v00Datbis":"09-07-2014","operand":"greater","v00Saicode":{"saiCode":"SO02","operand":"equals"}}
在控制器中,我得到这样的 JSON 字符串:
@RequestMapping(value = "/", method = RequestMethod.GET, headers = "Accept=text/plain")
public ResponseEntity<String> getVertagFromSearch(@RequestParam String allRequestParams, ModelMap model) throws JsonProcessingException{
//do stuff
}
更新 2
另一个大问题是合约的子域对象。 v00Saicode 依赖于合约。 日期也有同样的问题。如果没有将 JSON 字符串解析为合同对象,我会丢失 Calender 类的转换。 我真的储存了我应该如何在控制器中做出反应。有没有人有解决办法。
解决方案
这是我以动态方式完成所有部分的方式。
请求为操作员提供了额外的部分。
控制器收到这样的字符串:
@RequestMapping(value = "/", method = RequestMethod.GET, headers = "Accept=text/plain")
public ResponseEntity<String> getVertagFromSearch(@RequestParam String allRequestParams,@RequestParam String operators, ModelMap model) throws JsonParseException, JsonMappingException, IOException, IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
HashMap<String, String> operatorsMap = new ObjectMapper().readValue(operators, HashMap.class);
Contract contract = Contract.fromJsonToContract(allRequestParams);
List<Contract> list = Contract.findAllContractsPerContract(contract, operatorsMap);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
return new ResponseEntity<String>(Contract.toJsonArray(list),headers,HttpStatus.OK);
}
DAO 和对助手类的调用
public static List<Contract> findAllContractsPerContract(Contract contract, Map<String, String> operatorMap) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
EntityManager e = entityManager().getEntityManagerFactory().createEntityManager();
Session session = e.unwrap(Session.class);
Criteria criteria = session.createCriteria(Contract.class);
criteria = CriteriaBuilder.buildCriteria(contract, criteria, operatorMap);
List<Contract> list = criteria.list();
return list;
}
@Jeff 答案的 Criteria Builder 助手类和代码:
public static Criteria buildCriteria(Object object, Criteria criteria, Map<String,String> operatorMap) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException{
BeanInfo vertagInfo = Introspector.getBeanInfo(Contract.class);
for(PropertyDescriptor propertyDescriptor : vertagInfo.getPropertyDescriptors()){
String propertyString = propertyDescriptor.getName();
Object value = propertyDescriptor.getReadMethod().invoke(object);
if(propertyString.equals("class")||value==null){
continue;
}
String operator = operatorMap.get(propertyString);
if(operator==null){
operator="EQ";
}
criteria.add(Comparison.valueOf(operator).convert(propertyString, value));
}
return criteria;
}
【问题讨论】:
-
对于这个问题还有其他帮助吗?
-
我不明白你在控制器层的症结所在。您使用什么库将 JSON 解析为 Java 对象?您不必满足于合同对象或数据字符串;您应该能够创建 JSON 反序列化到的新 DTO(ContractCriteria 或其他东西),并且它可以具有内部日历成员。
-
@Jeff 更新后的答案唤醒了我。
标签: java hibernate jpa entitymanager hibernate-criteria