hibernate的qbc查询
Criteria查询也叫做QBC查询(Query By Criteria),这种查询方式是Hibernate提供的“更加面向对象”的一种检索方式,说白了都是操作对象的一些查询方法来查询,因此这个查询掌握起来难度相对要大些。
本篇文章的示例代码下载地址
https://download.csdn.net/download/qq_29001539/12280873
QBC查询方式
// 1.查询所有
// 2.条件查询
// 3.模糊查询
// 4.范围查询
// 5.排序查询(order by)
// 6.分页查询
// 7.投影查询(只获取部分字段的结果)
// 8.聚集函数使用(聚合函数)(count、sum、avg、max、min等)
// 9.TOP N查询
学习参考
- RESTRICTIONS用法:https://www.cnblogs.com/hahajava/p/9445480.html
- Hibernate—QBC查询(1):https://blog.csdn.net/an_2016/article/details/52003559
- Hibernate5.2值QBC查询:https://www.cnblogs.com/miller-zou/p/5737843.html
看到下面这张图有何感想,都是一些接口和实现类,主要的还是Criterion
父级层次接口,后面都是围绕他来进行展开操作查询的,每个对象的提供方法不同,不过呢,有一个工具类帮我们实现了条件的指定,它就是org.hibernate.criterion.Restrictions
,里面定义了不同的返回类型,但都始终是来自Criterion
下或者它自己(Criterion)的类型,修饰符号为static
,所以呢,我们可以直接通过类名称.方法的形式来调用具体方法。
1、查询所有
// 1.查询全部:获取所用用户信息
@Test
public void testList() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
2、条件查询
HQL运算符 | QBC运算方法 | 含义 |
---|---|---|
= | SimpleExpression eq(String propertyName, Object value) | 等于equal |
<> | SimpleExpression ne(String propertyName, Object value) | 不等于not equal |
> | SimpleExpression gt(String propertyName, Object value) | 大于greater than |
>= | SimpleExpression ge(String propertyName, Object value) | 大于等于greater than or equal |
< | SimpleExpression lt(String propertyName, Object value) | 小于less than |
<= | SimpleExpression le(String propertyName, Object value) | 小于等于less than or equal |
= | PropertyExpression eqProperty(String propertyName, String otherPropertyName) | |
<> | PropertyExpression neProperty(String propertyName, String otherPropertyName) | |
> | PropertyExpression gtProperty(String propertyName, String otherPropertyName) | |
>= | PropertyExpression geProperty(String propertyName, String otherPropertyName) | |
< | PropertyExpression ltProperty(String propertyName, String otherPropertyName) | |
<= | PropertyExpression leProperty(String propertyName, String otherPropertyName) | |
is null | NullExpression isnull(String propertyName) | 等于空值 |
is not null | NullExpression isNotNull(String propertyName) | 非空值 |
- Criterion allEq(Map<String,?> propertyNameValues) --> 参数为Map对象,使用key/value进行多个等于的比对,相当于多个Restrictions.eq的效果
- LogicalExpression and(Criterion lhs, Criterion rhs) 返回两个表达式的组合
- Conjunction and(Criterion… predicates),返回多个表达式的组合
// 2.1条件查询:查询id=1的指定对象
@Test
public void testGetById() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
/*
* 第一种方式:SimpleExpression eq(String propertyName, Object value)
*/
// criteria.add(Restrictions.eq("sid", 1));// 设置sid=1
/*
* 第二种方式:Criterion idEq(Object value)
* 该方式是根据你映射文件中hbm.xml配置里来的,id节点
* <id name="sid" column="sid">
* <generator class="native" />
* </id>
*/
criteria.add(Restrictions.idEq(1));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 2.2条件查询:查询指定班级成绩合格的信息
@Test
public void testGetClazzByPassScore() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
/*
* 第一种写法:分开添加
*/
// criteria.add(Restrictions.eq("clazz", "s1t87"));// clazz = s1t87
// criteria.add(Restrictions.ge("score", 61));// score >= 61
/*
* 第二种写法:LogicalExpression and(Criterion lhs, Criterion rhs)
*/
criteria.add(Restrictions.and(// clazz = s1t87 and score >= 61
Restrictions.eq("clazz", "s1t87"),
Restrictions.ge("score", 61)));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 2.3条件查询:查询性别男,成绩为100,clazz为s1t87的对象信息
@Test
public void testGetAllEq() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
/*
* 第一种写法:Criterion allEq(Map<String,?> propertyNameValues)
*/
// Map<String, Object> maps = new HashMap<String, Object>();
// maps.put("gender", "男");
// maps.put("score", 100);
// maps.put("clazz", "s1t87");
// criteria.add(Restrictions.allEq(maps));
/*
* 第二种写法:Conjunction and(Criterion... predicates)
*/
criteria.add(Restrictions.and(// 添加条件:gender="男",score=100,clazz="s1t87"
Restrictions.eq("gender", "男"),
Restrictions.eq("score", 100),
Restrictions.eq("clazz", "s1t87")));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 2.4条件查询:查询生日为空(null)的对象信息
@Test
public void testBirthIsNull() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
/*
* 第一种方法:Criterion isNull(String propertyName)
*/
// criteria.add(Restrictions.isNull("birth"));
/*
* 第二种方法: Criterion eqOrIsNull(String propertyName, Object value) 此方法有eq也有isNull
*/
criteria.add(Restrictions.eqOrIsNull("birth", null));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
3、模糊查询
谈谈like和ilike:刚开始link还比较好容易理解,就是一个模糊查询的关键字,但是iLike是什么东西???
翻了一下:LIKE和ILIKE操作符可以模糊匹配字符串,LIKE是一般用法,ILIKE匹配时则不区分字符串的大小写
。
https://blog.csdn.net/sinat_41928169/article/details/82718319
LIKE模式(一般的用法)
- SimpleExpression like(String propertyName, Object value)
- SimpleExpression like(String propertyName, String value, MatchMode matchMode)
iLIKE模式(该模式不分大小写)
- LikeExpression ilike(String propertyName, Object value)
- LikeExpression ilike(String propertyName, String value, MatchMode matchMode)
MatchMode(是一个枚举类),我理解成是一种匹配模式,或者是一个匹配策略,它有如下的几种策略:
- MatchMode.EXACT --> 字符串精确匹配.相当于"like ‘value’"
- MatchMode.ANYWHERE --> 字符串在中间匹配.相当于"like ‘%value%’"
- MatchMode.START --> 字符串在最前面的位置.相当于"like ‘value%’"
- MatchMode.END --> 字符串在最后面的位置.相当于"like ‘%value’"
// 3.1模糊查询:查询name含有“杰”的对象信息
@Test
public void testLikeName() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.like("name", "%杰%"));
// criteria.add(Restrictions.ilike("name", "杰", MatchMode.ANYWHERE));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 3.2模糊查询:查询name含有“c”的对象信息(不分大小写)
@Test
public void testLikeName1() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
// criteria.add(Restrictions.ilike("name", "%c%"));
criteria.add(Restrictions.ilike("name", "c", MatchMode.ANYWHERE));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
4、范围查询
- 介于两者之间(lo >>low,hi >> high),可以实现的方法
BetweenExpression
between(String propertyName, Object lo, Object hi) - 或者or,可以实现的方法
两者中:LogicalExpression
or(Criterion lhs, Criterion rhs)
多个:Disjunction
or(Criterion… predicates) - 包含in(列表),可以实现的方法
Disjunction
or(Criterion… predicates)
InExpression
in(String propertyName, Collection values)
InExpression
in(String propertyName, Object[] values)
// 4.1范围查询:查询成绩在80~100分范围的对象信息
@Test
public void testScopeBetweenScore() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.between("score", 80, 100));// 设置score的范围80~100(含80,100)
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 4.2范围查询:查找用户的密码是123456或者asdfghjkl这两种
@Test
public void testScopeOrPwd() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.or( // 添加一个or的条件,or的条件是123456和asdfghjkl
Restrictions.eq("pwd", "123456"), Restrictions.eq("pwd", "asdfghjkl")));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 4.3范围查询:查找用户的密码有123456、010101、555555、999999等范围
@Test
public void testScopeInPwd() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
/*
* 第一种方法:Disjunction or(Criterion... predicates)
*/
criteria.add(
Restrictions.or( // 添加多个范围的条件
Restrictions.eq("pwd", "123456"),
Restrictions.eq("pwd", "010101"),
Restrictions.eq("pwd", "555555"),
Restrictions.eq("pwd", "999999")));
/*
* 第二种方法:InExpression in(String propertyName, Object[] values)
*/
// String[] parPwd = { "123456", "010101", "555555", "999999" };
// criteria.add(Restrictions.in("pwd", parPwd));
/*
* 第三种方法:InExpression in(String propertyName, Object[] values)
*/
// List<String> pwdList = new ArrayList<String>();
// pwdList.add("123456");
// pwdList.add("010101");
// pwdList.add("555555");
// pwdList.add("999999");
// criteria.add(Restrictions.in("pwd", pwdList));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 4.4范围查询:查找班级不是s1t86、s1t87的
// (not in)技巧:其实就是加了一个 >>> not方法(in的查询方法)
@Test
public void testScopeNotClass () {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
/*
* 第二种方法:InExpression in(String propertyName, Object[] values)
*/
String[] parClazz = { "s1t86", "s1t87" };
criteria.add(Restrictions.not(Restrictions.in("clazz", parClazz)));
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
5、排序查询
- Order.asc --> 根据传入的字段进行升序排序
- Order.desc --> 根据传入的字段进行降序排序
// 5.排序查询:获取排序后的对象信息
@Test
public void testGetOrderList() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.addOrder(Order.asc("sid"));// 按照sid进行升序
// criteria.addOrder(Order.desc("sid"));// 按照sid进行降序
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
6、分页查询
// 6.分页查询
@Test
public void testPaging() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.setFirstResult(0);// 从0开始
criteria.setMaxResults(5);// 显示5条数据
List<User> lis = criteria.list();
for (User user : lis) {
System.out.println(user);
}
tx.commit();
session.close();
sessionFactory.close();
}
后面就要讲讲这个org.hibernate.criterion.Projections
的使用,这个是用来支持投影、聚合、分组的
方法 | 说明 |
---|---|
PropertyProjection groupProperty(String propertyName) | 获取某一个属性 |
ProjectionList projectionList() | 获取某几个属性 |
Projection distinct(Projection projection) | distinct |
Projection rowCount() | count(*) |
CountProjection count(String propertyName) | count(xxx) |
CountProjection countDistinct(String propertyName) | distinct count(xxx) |
7、投影查询
// 7.1投影查询:用于指定获取对象的某一个或某几个属性(返回数组)
@Test
public void testGetAppoint() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
/*
* 第一种方法:PropertyProjection property(String propertyName)
*/
// criteria.setProjection(Projections.projectionList()
// .add(Projections.property("sid"))
// .add(Projections.property("name"))
// .add(Projections.property("gender"))
// .add(Projections.property("clazz")));
/*
* 第二种方法:Property forName(String propertyName)
*/
criteria.setProjection(Projections.projectionList()
.add(Property.forName("sid"))
.add(Property.forName("name"))
.add(Property.forName("gender"))
.add(Property.forName("clazz")));
List<Object[]> lis = criteria.list();
for (Object[] objects : lis) {
System.out.println("sid:"+objects[0]+"---name:"+objects[1]+"---gender:"+objects[2]+"---clazz:"+objects[3]);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 7.2投影查询:查询所有的班级(去重复的值)
@Test
public void testGetClazzs() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.distinct(Property.forName("clazz")));// distinct clazz
List<String> lis = criteria.list();
for (String objects : lis) {
System.out.println("clazz:" + objects);
}
tx.commit();
session.close();
sessionFactory.close();
}
8、聚合函数
// 8.1聚合函数的使用:count统计总数据量
@Test
public void testCount() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.rowCount());// 获取总行数
Object obj = criteria.uniqueResult();// 获取唯一值
System.out.println(obj);
tx.commit();
session.close();
sessionFactory.close();
}
// 8.2聚合函数的使用:sum统计性别男、女的总人数
@Test
public void testSum() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
// select gender,sum(gender) from tableName group by gender
criteria.setProjection(Projections.projectionList()
.add(Property.forName("gender"))
.add(Projections.sum("gender"))
.add(Projections.groupProperty("gender"))
);
List<Object[]> obj = criteria.list();
for (Object[] objects : obj) {
System.out.println(objects[0]+"--"+objects[1]);
}
tx.commit();
session.close();
sessionFactory.close();
}
// 8.3聚合函数的使用:avg获取平均的分数
@Test
public void testAvgScore() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.avg("score"));
Object obj = criteria.uniqueResult();
System.out.println("平均成绩:"+ obj);
tx.commit();
session.close();
sessionFactory.close();
}
// 8.4聚合函数的使用:max获取最高的分数
@Test
public void testMaxScore() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.max("score"));
Object obj = criteria.uniqueResult();
System.out.println("最高的分数:"+ obj);
tx.commit();
session.close();
sessionFactory.close();
}
// 8.5聚合函数的使用:min获取最低的分数
@Test
public void testMinScore() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.min("score"));
Object obj = criteria.uniqueResult();
System.out.println("最低的分数:"+ obj);
tx.commit();
session.close();
sessionFactory.close();
}
9、TOP N查询
// 9.TOP N查询:返回s1t87班级中前五位分数最高的用户信息
@Test
public void testGetTopN() {
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
ProjectionList prList = Projections.projectionList();
prList.add(Projections.property("sid"));
prList.add(Projections.property("name"));
prList.add(Projections.property("score"));
prList.add(Projections.property("clazz"));
criteria.add(Restrictions.eq("clazz", "s1t87"))
.setProjection(prList
.add(Projections.property("sid"))
.add(Projections.groupProperty("score")))
.addOrder(Order.desc("score"))
.setFirstResult(0)// 结果从第一条开始
.setMaxResults(5);// // 只保留五条数据
List<Object[]> lis = criteria.list();
for (Object[] objects : lis) {
System.out.println("sid:" + objects[0] + "\tname:" + objects[1]
+ "\tscore:" + objects[2] + "\tclazz:" + objects[3]);
}
tx.commit();
session.close();
sessionFactory.close();
}