转载: http://blog.csdn.net/u014078192/article/details/24986475

一、Hibernate的三种查询方式(掌握)

Hibernate中提供了三种查询方式:

1)Session的查询:按主键查询查询,方法为get或load

2)Query的查询:使用HQL语句或SQL语句完成查询

3)Criteria的查询:通过方法和类中属性的关系,来设置查询条件,完成查询。

Session中get和load方法的区别?

1)  如果没有查询到数据,get会返回null,而load则直接提示错误。

2)  使用load查询时,可能会出现以下错误,因为load方式使用的是懒汉式加载方法。执行load方法时,不立刻查询数据库。当用到查询出的对象的属性时,才加载数据。

[java] view
plain
 copy

  1. org.hibernate.LazyInitializationException: could not initialize proxy - no Session

解决这个异常的方法:

1)  不关连接;2)不用load,就使用get就可以了

1.1、Query查询(重点)

1.1.1HQL语句不只支持查询功能,还支持修改以及删除功能

[java] view
plain
 copy

  1. public void doRemove(Integer id) throws Exception {
  2. // 注意,使用Hibernate删除时,必须先查询对象,再删除.
  3. // HibernateSessionFactory.getSession().delete(findById(id));
  4. String hql = "DELETE FROM News AS n WHERE n.id = ?" ;
  5. Query query = HibernateSessionFactory.getSession().createQuery(hql);
  6. query.setInteger(0, id);
  7. query.executeUpdate();
  8. }

注:使用HQL的删除可以不需要先查询,直接删除,支持一次删除多条数据

开发中的选择:1)当删除一条数据时,直接使用session.delete()就可以,因为简单,hibernate不在乎那点查询的性能;

2)批量删除时,使用Hql形式,这是可以提高性能的方法,因为它中间省去了查询的步骤。

1.1.2HQL语句修改功能

[java] view
plain
 copy

  1. public void doUpdate(News vo) throws Exception {
  2. // HibernateSessionFactory.getSession().update(vo);
  3. String hql = "UPDATE News AS n SET n.title = ?,n.content = ? WHERE n.id = ?" ;
  4. Query query = HibernateSessionFactory.getSession().createQuery(hql);
  5. query.setString(0, vo.getTitle());
  6. // ....其他参数一样设置
  7. query.executeUpdate();
  8. }

开发中的选择:1)如果是直接的修改功能,肯定选择session.update()方法;

2)如果是只修改某一字段,使用HQL方式。

注:HQL语句不支持添加,但是Query支持添加。

1.1.3针对HQL的查询功能,也支持写SELECT,可以通过编写SELECT,来只查询对象中某一个或某几个属性。

但是对于多种字段不同类型的查询返回的,Hibernate中只能是数组。

例如:

[java] view
plain
 copy

  1. public List testHQL() throws Exception {
  2. String hql = "SELECT n.id,n.title FROM News AS n";
  3. Query query = HibernateSessionFactory.getSession().createQuery(hql);
  4. return query.list();
  5. }

经过测试,发现当只查询一个字段时,直接返回该类型的List集合。

但查询两个以上的字段时,返回的是List<Object[]>,每一条查询出的数据,使用Object[]来表示,这就很不方便。

[java] view
plain
 copy

  1. public void testHQL() throws Exception {
  2. List all = ServiceFactory.getINewsServiceInstance().testHQL();
  3. Object[] value1 = (Object[]) all.get(0);
  4. System.out.println(value1[1]);
  5. }

这样使用起来很麻烦,因此在Hibernate3.2以上的版本中,提供了一个自动转换类,可以将查询出的Object[],自动转换为pojo 对象。

[java] view
plain
 copy

  1. public List testHQL() throws Exception {
  2. String hql = "SELECT n.id AS id,n.title AS title FROM News AS n";
  3. Query query = HibernateSessionFactory.getSession().createQuery(hql);
  4. <span style="color:#cc0000;">query
  5. .setResultTransformer(new AliasToBeanResultTransformer(
  6. News.class));</span>
  7. return query.list();
  8. }

注:一般开发中不会使用这种方法,只有当表中的字段过多,但查询只需要其中的几个字段时,才会用到这种方法。

1.1.4Hibernate还可以将语句写到配置文件中

[java] view
plain
 copy

  1. <query name="findAll">
  2. FROM News AS n WHERE n.title LIKE ?
  3. </query>

通过程序读取配置文件,取得这段HQL,并生成Query对象,完成查询。

[java] view
plain
 copy

  1. Query query = HibernateSessionFactory.getSession().getNamedQuery(
  2. "findAll");
  3. query.setString(0, "%测试%");
  4. return query.list();

这种方式在Mybatis中普遍使用,但是在Hibernate中一班很少这样做。

1.2、Criteria查询(了解)

Criteria也是Hibernate提供的一个查询对象,支持按对象的方式来完成查询。例如:

查询全部功能:

[java] view
plain
 copy

  1. public List<News> testCriteria() throws Exception {
  2. // 根据传入的pojo类型,查询该类型对应的全部数据
  3. Criteria c = HibernateSessionFactory.getSession().createCriteria(
  4. News.class);
  5. return c.list();
  6. }

如果想加入查询条件,需要使用Restrictions的各种方法来完成条件的拼写。

[java] view
plain
 copy

  1. public List<News> testCriteria() throws Exception {
  2. // 根据传入的pojo类型,查询该类型对应的全部数据
  3. Criteria c = HibernateSessionFactory.getSession().createCriteria(
  4. News.class);
  5. // 1、WHERE id = 26
  6. // c.add(Restrictions.eq("id", 26));
  7. // 2、WHERE id > 26
  8. // c.add(Restrictions.gt("id", 26));
  9. // 3、WHERE id < 26
  10. // c.add(Restrictions.lt("id", 26));
  11. // 4、WHERE id >= 26
  12. // c.add(Restrictions.ge("id", 26));
  13. // 5、WHERE id <= 26
  14. // c.add(Restrictions.le("id", 26));
  15. // 6、WHERE id <> 26
  16. // c.add(Restrictions.ne("id", 26));
  17. // 7、WHERE title LIKE '%测试%'
  18. // c.add(Restrictions.like("title", "%测试%"));
  19. // 8、WHERE id between 23 and 27
  20. // c.add(Restrictions.between("id", 23, 27));
  21. // 9、WHERE id IN (23,25,27)
  22. // List<Integer> allIds = new ArrayList<Integer>();
  23. // allIds.add(23);
  24. // allIds.add(25);
  25. // allIds.add(27);
  26. // c.add(Restrictions.in("id", allIds));
  27. // 10、复杂条件,需要使用and或or来连接各个条件
  28. // WHERE id = 23 OR (id <> 26 AND title LIKE '%测试%')
  29. c
  30. .add(Restrictions.or(Restrictions.eq("id", 23), Restrictions
  31. .and(Restrictions.ne("id", 26), Restrictions.like(
  32. "title", "%测试%"))));
  33. return c.list();
  34. }

如果想加入ORDER BY排序条件,需要使用Order对象。

[java] view
plain
 copy

  1. c.addOrder(Order.desc("id"));

如果想加入统计函数和分组函数,则需要用到Projection这个类

[java] view
plain
 copy

  1. <span style="white-space:pre">  </span>ProjectionList pro = Projections.projectionList();
  2. // 加入统计函数
  3. pro.add(Projections.rowCount());
  4. // 还可以加入分组条件
  5. pro.add(Projections.groupProperty("title"));
  6. c.setProjection(pro);

二、Hibernate中Session操作的三种状态

Session操作过程中的pojo对象存在三种状态:

1)  瞬时态:该对象在数据库中没有对应的数据。(刚new出来的数据)

2)  持久态:数据库中存在该对象对应的数据,同时操作该对象的Session也存在。

3)  游离态:数据库中包含该对象对应的数据,但操作此对象的Session已经不存在或被关闭了。

三种状态之间的转换:

瞬时 -->持久:save(),saveOrUpdate()

持久 -->瞬时:delete()

持久 -->游离:close()

游离 --> 持久:update(),saveOrUpdate()

针对持久态对象,Hibernate还存在以下两个特点:

1)  持久态对象,在同一Session中只存在同一个。

a)         如果连接不关闭,多次查询同一条数据,只返回同一个对象,也就是只查询一次数据库。

b)         此功能也被称为一级缓存,但实际开发中实用性很低。

2)  修改持久态对象的属性,可以自动同步到数据库对应的数据中。

a)         当修改了一个持久态对象的属性,而且提交了事务,则数据库自动调用更新操作,也一起修改。

b)        (用处) 当登陆后,要求将当前系统时间,作为最后登陆时间保存到数据库中时,可以使用。

三、Struts2 + Hibernate实现用户登陆功能

3.1先建立项目,根据需要加入框架支持

加入Hibernate:上一博客中详细介绍过,略

加入Struts2:右击项目名,在MyEclipse中找到Add Struts Capabilities;

点击next,只需加入它的核心Core Jar包就可以了;

点击Finish,即加好了struts的核心jar包;

3.2建立一张用户表

[sql] view
plain
 copy

  1. CREATE TABLE T_User (
  2. userid         varchar2(40)        primary key ,
  3. real_name      varchar2(20)        not null,
  4. password       varchar2(32)        not null,
  5. regist_date    date                default sysdate,
  6. last_login_date         date
  7. );
  8. INSERT INTO t_USER (userid,real_name,password)
  9. VALUES ('zhangsan','张三','123');
  10. commit;

根据表,在DB Browser下生成映射,主键使用assigned方式生成

3.3生成映射后,根据需要,完成DAO的方法和它的实现

DAO方法:

public boolean isLogin(TUser user) throws Exception;

DAOImpl实现:

[java] view
plain
 copy

  1. public class TUserDAOImpl implements ITUserDAO {
  2. public boolean isLogin(TUser user) throws Exception {
  3. String hql = "FROM TUser AS u WHERE u.userid = ? AND u.password = ?";
  4. Query query = HibernateSessionFactory.getSession().createQuery(hql);
  5. query.setString(0, user.getUserid());
  6. query.setString(1, user.getPassword());
  7. List<User> allUser = query.list();
  8. if (allUser != null && allUser.size() > 0) {
  9. // 登陆成功
  10. // 取得查询的结果
  11. TUser result = (TUser) allUser.get(0);
  12. // 根据引用传递,将值设置到传入的user中
  13. user.setRealName(result.getRealName());
  14. user.setRegistDate(result.getRegistDate());
  15. user.setLastLoginDate(result.getLastLoginDate());
  16. return true;
  17. }
  18. return false;
  19. }
  20. }

再实现Service以及工厂的代码。

工厂类:

public class DAOFactory{

public static ITUserDAO getITUserDAOInstance(){

return new TUserDAOImpl();

}

}

3.4后台代码实现后,开始编写前台Struts操作代码。

导入Struts2标签库,完成表单

[java] view
plain
 copy

  1. <%@ taglib uri="/struts-tags" prefix="s"%>

表单可以使用普通标签,也可以使用Struts2标签

[java] view
plain
 copy

  1. <span style="white-space:pre">      </span><center>
  2. <form action="tuser!login.action" method="post">
  3. 用户名:<input type="text" name="tuser.userid"/> <br/>
  4. 密码:<input type="password" name="tuser.password"/> <br/>
  5. <input type="submit" value="提交" />
  6. </form>
  7. //下面的为struts标签
  8. <s:form action="tuser!login" namespace="/" method="post" theme="simple">
  9. 用户名:<s:textfield name="tuser.userid"></s:textfield> <br/>
  10. 密码:<s:password name="tuser.password"></s:password> <br/>
  11. <s:submit value="提交"></s:submit>
  12. </s:form>
  13. </center>

编写Action类,完成验证的操作。

[java] view
plain
 copy

  1. public class TUserAction extends ActionSupport {
  2. private TUser tuser;
  3. public TUser getTuser() {
  4. return tuser;
  5. }
  6. public void setTuser(TUser tuser) {
  7. this.tuser = tuser;
  8. }
  9. public String login() throws Exception {
  10. boolean flag = ServiceFactory.getITUserServiceInstance().login(tuser);
  11. // 根据结果,决定跳转的位置
  12. if (flag) {
  13. // 将用户保存到session属性范围中
  14. ServletActionContext.getRequest().getSession().setAttribute("user",
  15. tuser);
  16. return "suc";
  17. }
  18. // 添加错误信息,页面使用标签显示
  19. super.addActionError("用户名或密码错误,请重新输入!");
  20. return "input";
  21. }
  22. }

配置这个Action,在struts.xml中完成。

[java] view
plain
 copy

  1. <struts>
  2. <package name="root" namespace="/" extends="struts-default">
  3. <action name="tuser" class="org.liky.login.action.TUserAction">
  4. <result name="suc">/pages/suc.jsp</result>
  5. <result name="input">/index.jsp</result>
  6. </action>
  7. </package>
  8. </struts>

完成suc.jsp中显示用户信息的功能

[java] view
plain
 copy

  1. <span style="white-space:pre">      </span><center>
  2. 用户登陆成功,当前登陆用户为: ${user.userid}
  3. </center>

在index.jsp中提示错误信息

[java] view
plain
 copy

  1. <span style="white-space:pre">      </span><font color="red">
  2. <s:actionerror/>
  3. </font>

测试项目,会提示以下错误信息。

java.lang.NoSuchMethodError:antlr.collections.AST.getLine()

这种错误是由于项目中加入了多个版本的支持jar包,各个版本之间有相同的类,但方法不同,造成冲突。

这里的冲突jar包是Struts2加入的2.7.2.jar造成的,需要将该包删除,该包是MyEclipse工具提供的,因此需要通过MyEclip-se的操作来删除,无法直接删除。

windows-->preference-->MyEclipse-->project capabilities-->Struts2中找到MyEclipse提供的antlr-2.7.2jar并删除。(这个jar包是MyEclipse自动加入的)

删除后,必须重新发布项目,并重新启动服务器才可以。

注:MyEclipse8.6就这两个冲突;7.5是冲突两个,少了三个;5.5是冲突一个,缺5个;

最好的做法备份项目Tomcat下的lib中的jar包,包含struts和Hibernate的所有jar包。

Hibernate 查询技术的更多相关文章

  1. 从零打造在线网盘系统之Hibernate查询与更新技术

    欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重 ...

  2. Hibernate查询之HQL查询

    转自:http://blog.csdn.net/xiao_yi/article/details/1733342 Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(H ...

  3. hibernate 查询、二级缓存、连接池

    hibernate 查询.二级缓存.连接池 查询: 1) 主键查询 Dept dept =  (Dept) session.get(Dept.class, 12); Dept dept =  (Dep ...

  4. Hibernate查询、连接池、二级缓存

    Hibernate第三天: 1. 对象状态 2. session缓存 3. lazy懒加载 4. 映射 一对一对映射 组件/继承映射 目标: 一.hibernate查询 二.hibernate对连接池 ...

  5. 六种方式实现hibernate查询,及IDE推荐

      这些天过的好乱,也许是因为考完试了,心里有些松懈吧.也许是最近发生的事对我有些触动吧.感觉自己都已经不懂自己了.面对一些人的教导,我很感激.因为很多话都对我有非常大的帮助和启发,也让我除了做技术, ...

  6. Hibernate查询

    HIbernate查询 使用get方法 使用get方法通过持久类名和ID号查找一个对象Stu instance = (Stu) getsession() .get("com.lovo.po. ...

  7. Hibernate 查询MatchMode的四种模式

    Hibernate 查询MatchMode的四种模式 MatchMode.START:字符串在最前面的位置.相当于"like 'key%'" MatchMode.END:字符串在最 ...

  8. hibernate查询方式

    hibernate查询方式:1.本地SQL查询 2.HQL查询 3.QBC查询 HQL查询:是面向对象的查询语言,是使用最广的一种查询方法 QBC查询:Query by Criteria是一套接口来实 ...

  9. Hibernate查询出现java.lang.IllegalArgumentException异常解决方法

    Hibernate查询出现java.lang.IllegalArgumentException. 异常信息如下:java.lang.IllegalArgumentException        at ...

随机推荐

  1. 关于PCB开窗

    如果走220V,那么线宽一点,一般高电压下面不覆铜 https://blog.csdn.net/zhy295006359/article/details/77412566 假设感觉需要走大电流,那么就 ...

  2. 上传头像,layui上传图片

    layui上传与bootstrap上传相似,只是不需要下插件, layui自带的已够用 先看一下前台界面,这里是用到的上传头像 先点击开始上传,头像上传至服务器中, 返回json添加至form表单中, ...

  3. ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)

    什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互.这种攻击是完全有可能的 ...

  4. Luogu3191 HNOI2007 紧急疏散 二分答案、最大流

    传送门 题意:自己去看 考虑二分答案.$BFS$预处理出每一个人到每一扇门的最短时间,设二分的值为$mid$,那么把门拆成$mid$个点,每一个点代表第$1,2,...,mid$秒时的状态.$i-1$ ...

  5. odoo订餐系统之类型设计

    这次开发的模块是订餐的类型设计,比如大荤 小荤 蔬菜 米饭 等基本数据.1.设计model类,很简单就一个字段: class MyLunchProductionCategory(osv.Model): ...

  6. Luogu P1447 [NOI2010]能量采集

    Preface 最近反演题做多了看什么都想反演.这道题由于数据弱,解法多种多样,这里简单分析一下. 首先转化下题目就是对于一个点\((x,y)\),所消耗的能量就是\(2(\gcd(x,y)-1)+1 ...

  7. python中和生成器协程相关的yield from之最详最强解释,一看就懂(四)

    如果认真读过上文的朋友,应该已经明白了yield from实现的底层generator到caller的上传数据通道是什么了.本文重点讲yield from所实现的caller到coroutine的向下 ...

  8. Jmeter(三十)_TimeShift函数在JSR223中的使用

    今天学习一下TimeShift函数在JSR223中的使用方法. 关联之前的一篇时间戳文章:Jmeter(十二)_打印时间戳 首先,创建线程组,在线程组下面创建一个JSR223采样器 选择Groovy语 ...

  9. Vue命令(一)

    Vue Command Summary 1.v-bind:元素节点的title属性和message保持一致. <div id="app-1"> <span v-b ...

  10. iOS Runloop理解

    一.RunLoop的定义 当有持续的异步任务需求时,我们会创建一个独立的生命周期可控的线程.RunLoop就是控制线程生命周期并接收事件进行处理的机制. RunLoop是iOS事件响应与任务处理最核心 ...