前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据库:Criteria与原生SQL查询

数据库:Criteria与原生SQL查询

作者头像
用户10175992
发布2023-10-17 10:35:57
3430
发布2023-10-17 10:35:57
举报
文章被收录于专栏:辰远辰远

1 Criteria查询

Hibernate除了提供强大的HQL查询之外,还提供了一种称为Criteria的查询方法。HQL和SQL很相似,其特点是灵活和功能丰富,但缺点是使用者必须熟悉SQL的语法,而且在组合条件查询时,常常需要拼装Where条件,还得为条件提供参数。而Criteria查询更加面向对象,和Java代码结合得更好,在组合条件查询时往往更加方便。当然,Criteria也有其缺点,其可读性不如HQL高,功能也不如HQL多。         Hibernate官方往往更推荐使用HQL去解决问题。

1.1Criteria的使用方法。

Criteria criteria = sess.createCriteria(Category.class);     //创建持久化类的查询对象Criteria         criteria.add(规则);                                                             //设置查询规则criterion         List list = query.list();                                                          //获取查询结果

 1.2规则-Criterion

Criterion 是Criteria的查询条件。Criteria 提供了add(Criterion criterion)方法来添加查询条件。Criterion 接口的主要实现包括:Example 、Junction和SimpleExpression。Junction 的实际使用是它的两个子类 conjunction 和 disjunction ,分别是使用 AND 和 OR 操作符进行来联结查询条件集合。 Criterion的实例可以通过Restrictions工厂类来提供,Restrictions 提供了大量的静态方法,如 eq(等于)、 ge(大于等于)、between等来方法的创建Criterion查询条件 (SimpleExpression实例)。除此之外,Restrictions还提供了方法来创建conjunction和 disjunction实例,通过往该实例的 add(Criteria) 方法来增加查询条件形成一个查询条件集合。 Restrictions中的静态方法条件 含义 Criteria HQL 等于 Restrictions.eq() = 不等于 Restrictions.not(Exprission.eq()) <> 大于 Restrictions.gt() > 大于等于 Restrictions.ge() >= 小于 Restrictions.lt() < 小于等于 Restrictions.le() <= 等于空 Restrictions.isnull() is null 非空 Restrictions.isNotNull() is not null 模糊查询 Restrictions.like() like 逻辑与 Restrictions.and() and 逻辑与 Restrictions.conjunction() and 逻辑或 Restrictions.or() or 逻辑或 Restrictions.disjunction() or 逻辑非 Restrictions.not() not 等于某一个值 Restrictions.in() in( ) 不等于任一个值 Restrictions.not(Restrictions.in()) not in() 区间 Restrictions.between() between x and y 不在区间内 Restrictions.not(Restrictions..between()) not between x and y (1)为Criteria添加简单类型属性限制(查询条件)。         Criteria criteria = sess.createCriteria(Movie.class);         criteria.add(Restrictions.like("title", "%狂%"));         List<Movie> list = criteria.list(); (2)为Criteria添加关联类属性限制。         直接使用criteria的add()方法,仅能添加简单类型属性限制和对于关联类的Id属性限制。若要添加关联类的其它属性限制(如为Movie实体添加关联类Category的name属性限制,必须重新createCriteria()并把关联属性名作为参数传入,然后就可以使用关联类Category的属性作为限制条件。         Criteria criteria = sess.createCriteria(Movie.class);         criteria = criteria.createCriteria("category");                   //重新执行createCriteria()         criteria.add(Restrictions.eq("name","动漫"));         List<Movie> list = criteria.list();         上述的效果还可以通过criteria的createAlias()方法实现,与createCriteria不同,它只是给关联实体起一个别名,使用createAlias后依然可以使用被查询对象的其它属性作为限制。         List<Movie> list = sess.createCriteria(Movie.class) .createAlias("category", "c")                                                   .add(Restrictions.eq("c.name", "战争"))                                                   .add(Restrictions.like("title", "风%"))                                                   .list();

 1.3用实体一次声明多个等于或者like规则的限制条件-Example

Example也是一种添加Criteria规则的方式,这种方式使用一个查询实体类的对象,一口气声明多个规则。Example 的创建有所不同,Example 本身提供了一个静态方法 create(Object entity),参数是一个实体对象(实际使用中一般是映射好的实体对象)来创建。然后可以设置一些过滤条件:         Example example = Example.create(entity)                                                            .ignoreCase()   // 忽略大小写                                                            .enableLike(MatchMode.ANYWHERE);  //使用like         criteria.add(example);         List list = criteria.list()

1.4实现排序

你可以使用Criteria的addOrder(Order order) 控制查询结果的顺序。Order对象实例可以通过Order.asc("属性名") 和Order.desc("属性名")获取。         List cats = sess.createCriteria(Cat.class)                                   .add( Restrictions.like("name", "F%")                                   .addOrder( Order.asc("name") )                                   .addOrder( Order.desc("age") )                                   .list() ;

1.5 实现分页

Criteria对象与Query对象一样可以通过setFirstResult() 和setMaxResults()方法实现分页

1.6 投影Projection—实现聚合函数和分组

Criteria可以通过setProjection(Projection projection)方法实现聚合统计和分组。 Projection主要是让Criteria能够进行统计查询,并可以实现分组。Projection主要有   SimpleProjection和ProjectionList实现。其中 SimpleProjection 和 ProjectionList 的创建是通过内建的 Projections静态方法来完成的,如提供的avg()、count()、max()、min()、sum()可以让开发者很容易对某个字段进行统计查询。Projections的groupProperty()方法还可以对结果进行分组。         ProjectionList projectionList = Projections.projectionList();         Projection prjCount = Projections.count("id");         projectionList.add(prjCount);         projectionList.add(Projections.groupProperty("category"));         criteria.setProjection(projectionList);         List<Object[]> list = criteria.list();

1.7 DetachedCriteria

DetachedCriteria类和Criteria接口功能很类似,可以使用上述提到的方式(Criterion与Projection)设置查询条件,但两者的创建方式不同:Criteria必须由Session对象创建,而DetachedCriteria创建时不需要Session对象。因此DetachedCriteria可以在Session作用域之外构建,并添加一系列复杂条件,然后传递到具有Session环境的Dao方法中执行。DetachedCriteria的出现实现了“条件构建”和“查询执行”的分离。

代码语言:javascript
复制
public static void main(String[] args) {
		DetachedCriteria cri = DetachedCriteria.forClass(Movie.class);
		cri.add(Restrictions.eq("category.id", 1));
		List<Movie> list = get(cri);
		for(Movie m: list){
			System.out.println(m.getTitle()+","+m.getCategory().getName());
		}
	}
	static List get(DetachedCriteria cri){
		Session sess = null;
		try {
			sess = HibernateUtil.getSession();	
			return cri.getExecutableCriteria(sess).list();
		} finally {
			if(sess!=null)
				sess.close();
		}
	}

2 原生SQL操作

2.1 原生SQL查询

虽然HQL已经足够强大,但由于不同的数据库系统对标准SQL有不同的扩展(如SQL Server的T-SQL、Oracle的PL/SQL,Hibernate中称作方言“Dialect”),因此HQL无法100%完成我们在本地SQL中可以实现的功能。而且HQL最终还是要转换到SQL执行的,这种自动转换总有不如人意的地方,过于复杂的HQL转换成SQL后,执行效率可能会较低。为此,Hibernate还保留了我们直接使用数据库本地SQL的权利,我们可以直接编写SQL语句,控制查询结果。值得注意的是,一旦使用了本地SQL,若将来为数据访问层切换另一种数据库系统时,就需要修改这些本地SQL,使之符合新的数据库方言。

(1)返回基本类型Object数组的本地SQL查询。

本地SQL查询与HQL查询的用法基本相似,不同的是SQL查询需要使用Session的createSQLQuery(String sql)方法,返回的查询对象为SQLQuery类型。

String sql = "select m.Title, c.name from Movie m inner join Category c on m.CategoryId=c.Id where c.name=:cname";

SQLQuery query = sess.createSQLQuery(sql);

query.setString("cname", "战争");

List<Object[]> list = query.list();

(2)直接返回映射实体的本地SQL查询。

我们常常希望通过本地SQL查询返回持久化实体对象,若用上述的方式,Hibernate的返回结果是基本类型的Object数组,要获取实体,还需要重新构建实体对象和设置属性。为了简化我们的工作,SQLQuery接口对象直接提供了addEntity(String alias, Class entityClass)方法,可以帮助我们直接把SQL结果填充到实体对象,返回实体对象数组和列表。

代码语言:javascript
复制
String sql = "select m.*, c.* from Movie m inner join Category c on m.CategoryId=c.Id where c.name=:cname";
SQLQuery query = sess.createSQLQuery(sql);
query.addEntity("m",Movie.class);
query.addEntity("c",Category.class);
query.setString("cname", "战争");
List<Object[]> list = query.list();
for(Object[] arr : list){
        Category c = (Category)arr[1];
        Movie m = (Movie)arr[0];
        System.out.println( c.getName() + "," + m.getTitle());
}
2.2 原生JDBC操作

如果想更灵活的使用原生JDBC操作增删改,则可以使用Session对象提供的doWork方法,通过Work接口编写内部匿名类,我们可以调用JDBC的底层API来实现批量操作。

Session.doWork() 方法的执行方式如下所示。

代码语言:javascript
复制
Session session=HibernateUtil.openSession();
	Transaction transaction=session.beginTransaction();
	session.doWork(new Work() {
			public void execute(Connection conn) throws SQLException {
				//这里是SQL非HQL
				String sql = "delete from Movie where categoryId=?"; 
				PreparedStatement stmt = conn.prepareStatement(sql);
				stmt.setInt(1, 2);
				stmt.executeUpdate();
			}
	});
	transaction.commit();
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-12-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 Criteria查询
    • 1.1Criteria的使用方法。
      •  1.2规则-Criterion
        •  1.3用实体一次声明多个等于或者like规则的限制条件-Example
          • 1.4实现排序
            • 1.5 实现分页
              • 1.6 投影Projection—实现聚合函数和分组
                • 1.7 DetachedCriteria
                • 2 原生SQL操作
                  • 2.1 原生SQL查询
                    • 2.2 原生JDBC操作
                    相关产品与服务
                    数据库
                    云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档