在本文的结尾,您将找到要下载的源代码。
什么是标准? 当前是创建动态查询的最佳解决方案。 想象一下一个页面,该页面允许用户执行几种类型的查询; 所请求的查询可以是按名称,按年龄或二者兼有。 让我们看一下如果连接一个String时查询的外观:
EntityManager em = emf.createEntityManager();
String hql = "select p from Person p where 1=1 ";if(parameters[0].equals("name")){hql += " and p.name = '" + values[0] + "'";
}if(parameters[1].equals("age")){hql += " and p.age = " + values[1];
}TypedQuery<Person> query = em.createQuery(hql, Person.class);System.out.println(query.getResultList());
注意,在上面的代码中进行了字符串连接; 请记住,这种做法是一种不良和危险的做法,因为它允许“ SQL Injection”黑客攻击。 为了避免这种攻击,我们应该使用带有参数的查询:
EntityManager em = emf.createEntityManager();
String hql = "select p from Person p where 1=1 ";if(parameters.contains("name")){hql += " and p.name = :name";
}if(parameters.contains("age")){hql += " and p.age = :age";
}TypedQuery<Person> query = em.createQuery(hql, Person.class);if(parameters.contains("name")){query.setParameter("name", values[0].toString());
}if(parameters.contains("age")){query.setParameter("age", Integer.valueOf(values[1].toString()));
}System.out.println(query.getResultList());
注意,SQL注入问题已解决,但是现在代码必须检查参数以将其添加到查询中,并在以后传递其值。 代码需要两个“参数搜索”来完成任务。
Java / Oracle开发人员在创建适用于这种情况的Criteria概念时有一个绝妙的主意。 在下面,使用本地JPA标准检查代码的外观:
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
cq.select(root);if(parameters.contains("name")){Path<String> name = root.get("name");cq.where(cb.and(cb.equal(name, values[0])));
}if(parameters.contains("age")){Path<Integer> name = root.get("age");cq.where(cb.and(cb.equal(name, Integer.valueOf(values[1].toString()))));
}TypedQuery<Person> query = em.createQuery(cq);System.out.println(query.getResultList());
有可能看到传递参数值更加容易。 无需连接字符串或检查参数列表值以填充值。
不幸的是,Criteria API过于复杂和冗长。 如果您只想“从人物p中选择p”,则需要创建以下条件:
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
cq.select(root);TypedQuery<Person> query = em.createQuery(cq);
System.out.println(query.getResultList());
对许多代码来说,如此简单就可以从表中列出所有人。
为了避免所有这些冗长的细节,创建了名为EasyCriteria的开源项目。 如果开发人员使用EasyCriteria,则上面的查询如下所示:
EntityManager em = emf.createEntityManager();
EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(em, Person.class);if(parameters.contains("name")){easyCriteria.whereEquals("name", values[0]);
}if(parameters.contains("age")){easyCriteria.whereEquals("age", values[1]);
}System.out.println(easyCriteria.getResultList());
请注意,所有JPA详细信息都已消失。 现在可以使用干净的代码,更轻松地创建动态查询。 关于上面的代码值得一谈:
- 第2行:通过“工厂”创建EasyCriteria的实例。 该工厂的存在是为了对创建EasyCriteriaImp类型的对象所需的所有陡峭对象进行抽象。 在将来的版本中,将添加新类型的EasyCriteria,例如“ Tuple”。
- 第5和9行:传递参数更容易。 要将参数传递给比较值(“ name =:name”),只需使用equals方法,该方法将属性名称作为第一个参数。 第二个参数将是等于的值。
- 第12行:要运行查询,就不必使用Query界面。 EasyCriteria本身承担此责任。 可以通过EasyCriteria提取查询结果。 有两种方法可用于获取查询结果:EasyCriteria.getSingleResult(),EasyCriteria.getResultList()。
在EasyCriteria网页上,可以找到几个代码示例以及可以使用的方法。 EasyCriteria的另一个优点是可以“链接”所有方法:
easyCriteria.whereEquals("name", values[0]).whereEquals("age", values[1]).getResultList();
这是一个轻量级的库,因为唯一的依赖关系是系统将需要的JPA。 注意:您的应用程序将需要启动并运行JPA实现。
该库是使用JUnit开发的,并已通过Hibernate,OpenJPA和EclipseLink进行了测试。 JUnit还使用Cobertura框架来检查测试是否覆盖了所有代码行(或其中大部分),到目前为止,我们已覆盖了100%。
EasyCriteria仍处于Beta版,但开发团队已经计划了一些版本和功能。
EasyCriteria的另一个优点是您的软件代码不再“耦合”到任何类型的JPA实现中。 今天,Hibernate具有良好的条件工具,但是您的代码必须保持“附加”状态。 使用EasyCriteria,您将能够使用任何一种JPA实现。 这个解耦库的证明是EasyCriteria已通过前面引用的3种实现进行了测试。
EasyCriteria具有以下方法:in,like,empty和其他。 开发人员将能够使用Criteria进行连接(只是不带参数的简单连接),所有人都可以区分甚至排序。
在这里,您将找到EasyCriteria,可以下载并访问其所有文档。
单击此处下载此帖子的源代码。
我希望这篇文章/工具可以对您有所帮助。
参考: EasyCriteria –通过 uaiHebert博客的JCG合作伙伴 Hebert Coelho 使用JPA Criteria的简便方法 。
翻译自: https://www.javacodegeeks.com/2012/07/easycriteria-easy-way-to-use-jpa.html