hibernate常用API详解(原创)(2)

2020-04-16 12:10

3-3使用Criteria来实现查询

其实Criteria出现的主要原因就是为了处理复杂的条件查询,开发人员在使用SQL编写复杂查询条件时很容易出错,Hibernate就提供了Criteria这样一个方便的API,开发人员用Java来写查询条件,最后由Hibernate转换成SQL去执行。

Criteria crit = baseDao.getCriteria(Member.class); crit.add(Restrictions.like(\, \)); crit.add(Restrictions.in(\, new String[]{\,\,\})); crit.add(Restrictions.eq(\, 0)); List lstM = crit.list(); for (Member member : lstM) { }

Criteria对象通过add方法添加查询条件,Restrictions提供了各种各样的查询条件API:like、in、eq、between、or等等。这里要注意一点:像Restrictions.like(key,value)这些方法的key就是POJO中的属性,而不是数据库中的字段!

4、有时候我们调用SQL时不希望查询出表的所有字段(特别是大数据量项目更要考虑),使用纯JDBC写这样的SQL就能实现,但是如果用JDBC,得到值后还要通过ResultSet.getXXX来获取对应数据,这种方式非常麻烦。Hibernate提供了很多解决方案,使我们摆脱频繁的getXX操作。

以此为例:我希望查询Member表的id和fk_userinfo这两个字段

4-1HQL获取指定字段推荐采用面向对象的形式来实现

什么意思呢,假设Member类有一个构造函数Member(int id,int fkId),我们通过new Member(xx,xx)赋值这样就把值放入Member中了,使用HQL也是这样的: 第一步编写Member构造函数

public BaseMember(Integer id, Integer fkId) { }

第二步编写HQL,注意看SELECT后面的写法,这种写法看起来非常像Java的new Member是吧,只要这样写,通过Query.list()返回的结果就直接存放在List中了 Query query = baseDao.getQuery(\Member(m.id,m.fkUserinfo.id) FROM Member m\); List lstM = query.list(); for (Member member : lstM) { }

System.out.println(\+member.getId()+\fk_id:\+member.getFkUserinfo().getId());

this.id = id;

Userinfo fkUserinfo = new Userinfo(fkId); this.fkUserinfo = fkUserinfo;

System.out.println(\+member.getId()+\fk_id:\+member.getFkUserinfo().getId());

两点说明:

①理论上在编写上面那句

HQL

时可以这样写的:SELECT NEW

Member(m.id,m.fkUserinfo.id) FROM Member m(就是把Member的包名去掉),因为Member类是在Hibernate映射文件Member.hbm.xml中指定了路径的。但是Member在HQL里面是关键字,如果不加包名执行查询的话会报如下错误:java.lang.ClassCastException: org.hibernate.hql.ast.tree.SqlNode cannot be cast to org.hibernate.hql.ast.tree.PathNode。那么如果POJO对象不是*.hbm.xml中映射的类,则注意一定要加上POJO的全路径!

②上面HQL语句有这样一段代码“m.fkUserinfo.id”,这是一种面向对象的写法,表示m对象(Member)下的fkUserinfo属性(Userinfo)下的id,之所以这样写是因为Member表里的fk_userinfo外键关联Userinfo表的id,在编写hbm.xml时通常是将字段fk_userinfo设置成Userinfo对象方便关联自动查询,这也就是为什么在1-1例子中调用.getName()时会自动发送SQL的原因。

4-2使用SQL查询字段

在1-2中我使用setEntity将SELECt *查询出的数据直接映射到Member集合中,但是如果只查询Member表的部分字段就不能这样写了,先看下面这段可正确运行的代码: SQLQuery sql = baseDao.getSQLQuery(\m.id,m.login_code,m.fk_userinfo FROM Member m\); sql.addScalar(\, Hibernate.STRING); sql.addScalar(\, Hibernate.INTEGER); List lstM = sql.list(); for (Object[] objects : lstM) { }

上面这段代码有几个功能点:

①通过SELECT x.xx,x.xxx FROM xx x格式查询出的数据是返回一个List集合,也就是List每一条数据是一个Object数组,代表一行字段,在迭代List集合后通过object[下标]取每个字段数据即可;

②addScalar(字段名,类型名)用于设置返回字段的类型,Hibernate有默认设置字段类型功能,但是如果你希望明确指定每个字段的类型则必须这么写;

③上面的SQL语句是查询三个字段“m.id,m.login_code,m.fk_userinfo”,但是结果只返回了两个字段的数据,如果在lstM循环体内写objects[2]会报下标越界错误,这是因为addScalar时只设置了login_code和id两个字段,所以要注意如果你希望查询多个字段,而且又希望通过addScalar方法设置返回类型则所有查询的字段都要调用addScalar方法!

④返回的Object数组的值顺序与SQL语句中不同,SQL语句是依照id、login_code的顺序查询,而结果却是login_code、id的顺序返回,这还是因为addScalar方法,返回值是根据addScalar方法顺序来设置值的!

⑤如果只查询Members表的几个字段不能使用addEntity直接将映射到实体中,会报找不到字段值的错误,因为有几个字段是没查询的。

4-3Criteria没有找到返回特定字段的方法,如果谁有解决方案麻烦告知我一声。

5、前面介绍了查询的各种方法,这里再介绍一下通过HQL/SQL执行增删改操作。

增删改都是能改动表结构,所以调用的方法都是相同的,只是语句不同而已,同时需要考虑事务

System.out.println(\

(在执行语句前开启事务,执行语句后提交事务)这样才能保证数据完整性。 5-1 使用HQL实现删除操作

HQL删除是非常简单的,同样创建Query对象,然后调用executeUpdate方法即可,该方法能处理INSERT、UPDATE和DELETE语句。

Query q = baseDao.getQuery(\10\);

System.out.println(\删除影响行数:\+q.executeUpdate());

5-2使用SQL实现删除操作

SQL删除也是非常简单的,同样创建SQLQuery对象,然后调用executeUpdate方法即可,该方法能处理INSERT、UPDATE和DELETE语句。 SQLQuery q = baseDao.getSQLQuery(\FROM Member WHERE login_code in (:login_code)\);

q.setParameterList(\, new String[]{\,\,\});

System.out.println(\删除影响行数:\+q.executeUpdate());

6、介绍Hibernate内置的几个经典API 6-1使用

新增一个POJO到数据库:this.getSession().save(arg0)传入参数是一个POJO对象,一定要有hbm.xml映射,Hibernate会根据对象类型发送新增SQL到数据库

更新一条表数据,:this.getSession().update(arg0)传入参数是一个POJO对象,必须有ID,Hibernate会根据id更新数据,而且此方法会将POJO对象所有属性进行更新,也就是说假设Member表login_code为”kaka”,而执行update时Member对象中的logincode未设值,则最终表的login_code值会为null

删除一条表数据:this.getSession().delete(arg0)传入参数是一个POJO对象,必须有ID,其它属性值可以不要

查询操作this.getSession().get(arg0, arg1)传入参数arg0:POJO的Class,参数arg1:POJO的id,根据主键id查询一条字段数据

延迟查询 this.getSession().load(arg0, arg1)传入参数与上面的get方法相同,功能也是根据id查询一条字段,唯一不同的是:get是调用该方法就发送SQL语句并返回数据;load是当使用返回对象时才发送SQL语句查询,如下代码 Member m = …load(Member.class,id); Thread.sleep(1000); m.getId();

上面的代码肯定要发一条SQL语句查询Member表,如果用的是load方法,则是在睡眠完成运行m.getId()才发送SQL语句;而如果用的是get方法,则是在调用get方法就发送SQL语句了。

6-2经典的更新操作

从6-1的update语句中我们能看到一个弊端:不能定制更新个别字段,只能更新全部字段。Hibernate提供了一种持久化状态的更新机制,这种更新方法非常奇妙:

Member member = (Member) getSession().get(Member.class, id); member.setLoginCode(\); member.setPassword(\);

猜想上面这段代码会发几句SQL?根据控制台调试发现总共发了两句SQL:一句是SELECT语句查询Member表,另一句是UPDATE语句更新Member表字段,最终查询数据库时发现logincode和password的值都变成了上面设置的值。

这是一种非常好使的UPDATE方法,不用写SQL语句,直接先get后set即可自动发送SQL。

以上介绍的是非常通用的Hibernate API,当然Hibernate还提供了很多其它优秀的功能,比如缓存、复杂映射等等,这些技术需要大家在学会通用API之后再深入了解。


hibernate常用API详解(原创)(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:阅读材料2-基于TransCAD的公交线网评价指标

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: