1.get() 采用立即加载方式,而 load() 采用延迟加载;
2.get() 方法执行的时候,会立即向数据库发出查询语句,而 load() 方法返回的是一个代理(此代理中只有一个 OID 属性),只有等真正使用该对象属性的时候,才会发出 sql 语句并执行 3.如果数据库中没有对应的记录 , get() 方法返回的是 null . 而 load() 方法出现异常 ObjectNotFoundException

我在数据层中封装了一个 load() 方法,根据用户 Id 获取用户对象:

public UserModel getUserById(Long uuid) {return this.getHibernateTemplate().load(UserModel.class, uuid);//return this.getHibernateTemplate().get(UserModel.class, uuid);}

当在业务层调用了这个方法后,获得一个 userModel 对象,当展示用户信息时,就会报出 noSession 问题,

public String get(){//报出了 org.hibernate.LazyInitializationException: could not initialize proxy - no Session异常UserModel temp = userEbi.get(1L);System.out.println(temp.getName());System.out.println(temp.getAge());return "haha";}

报出的异常如下:

原因:

这是因为数据层提供的 load() 方法具有延迟加载的特性,在调用 load方法时,Hibernate 不会立即执行 sql 语句,而是动态的生成一个 UserModel 的代理对象实例,这个代理对象只具有 OID,也就是 uuid 值【这个值来自于形参,而不是数据库】,该对象的其他信息都没有。

这个动态代理对象所具有的特性有:

  1. 代理类对象和真实的 UserModel 对象无异,但是只具有 OID,其他属性均为 null,所以会比较省内存,这也是延迟加载的好处
  2. 当第一次访问这个代理类对象时,调用器 getXxx 方法时不会出问题,Hibernate 才会初始化这个代理对象,并会自动去执行 sql 语句去查询其数据库中的数据,【也就是 Service 层中的同一个方法,一旦这个方法弹栈,即事务提交结束,session 被关闭,】。

当需要这个只具有 OID 的代理对象传递到了业务层(如果在事务关闭session之前立马进行二次查询,就不会出问题),此时对象仍是一个延迟加载对象(只具有 OID),如果传递到了表现层(action内),此时该对象依然是延迟加载对象(但此时早在业务层,方法早已弹栈,事务就已经将 session 关闭了,一旦要进行二次查询就会报异常, 因为 session对象已经被刷新了,也就是连接断开了,session 中存储的数据早已丢失),值得一说的是在表现层使用二次查询是比较正常的需求。

解决这个问题有三个途径:

  • 在全局取消延迟加载数据
  • 在局部取消延迟加载数据
  • 将 session 的范围扩大,扩大到表现层【此时就是 action 内 】

第一种:在全局取消延迟加载数据,【这里的全局指的是某个表,并不是整个数据库】

<?xml version="1.0"?>  <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  <hibernate-mapping package="com.msym.entity">  <!-- 取消对于 user_db 表的延迟加载属性 -->  <class name="User" table="user_db" lazy="false" >  <id name="id">  <generator class="identity"/>  </id>  <property  name="password" />  <property  name="name" /><property  name="nickName" />    <property  name="age" />  <property  name="birthday" />  </class>  </hibernate-mapping>

优点:简单方便;

缺点:对于这个表,取消了延迟加载,在很多情况下会导致内存占用大的问题,取出了原本不需要的数据。

第二种:在局部取消延迟加载,【在 Service 层和 dao 层都可以局部取消延迟加载属性】

public UserModel getUserById(Long uuid) {UserModel u =  this.getHibernateTemplate().load(UserModel.class, uuid);Hibernate.initialize(u);return u;//return this.getHibernateTemplate().get(UserModel.class, uuid);}

优点:相比第一种,更加具有针对性,更加的灵活;

缺点:代码量稍稍多了一点点【但是也不要紧】。

第三种:扩大 session 的范围,

也就是要做到当前 session 在 Service 层的方法弹栈后不随事务的提交而关闭,直到一次请求与响应完成才关闭。这时用到的一个技术就是 openSessionInView,将 session 与当前请求对应的线程绑定在一起【此 session 并非浏览器会话级别的 session,而是数据库连接的 session】,这需要在 web.xml 中配置一个过滤器,这时注解的事务的任务就是开启事务,刷新事务;关闭事物的功能交给了 OpenSessionInViewFilter 这个类了,因为这个过滤器配置在一个,请求对象 request 最先接触到它,请求结束时的最后一个过滤器也是它(这就是过滤器链了,往返要都过滤一次)。代码在下面:(一定要将 OpenSessionInViewFilter 配置在所有过滤器的前面)

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><!-- applicationContext对象加载仅加载一次,服务器启动时加载,使用web中的监听器机制 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><!-- OpenSessionInView解决noSession问题,一定要配置在核心过滤器的前面 --><filter><filter-name>openSessionInView</filter-name><filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class><init-param><param-name>sessionFactoryBeanName</param-name><param-value>sessionFactory</param-value></init-param><init-param><param-name>singleSession</param-name><param-value>true</param-value>           </init-param><init-param><param-name>flushMode</param-name><param-value>AUTO</param-value>        </init-param>
    </filter><filter-mapping><filter-name>openSessionInView</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- struts核心过滤器 --><filter><filter-name>struts2</filter-name><filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class></filter><filter-mapping><filter-name>struts2</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>

OpenSessionInViewFilter 配置了三个参数:singleSession,sessionFactoryBeanName ,flushMode,

这几个属性都有其默认值,分别是,true,SessionFactory,MANUAL【手动提交事务】。

其中只是将 flushMode的默认属性修改了,是为了防止出现 FlushModel 相关的异常。

因为上面使用的是【org.springframework.orm.hibernate3.support.OpenSessionInViewFilter】这些属性在其中都能找到,

但是如果使用的是 hibernate4.support 的话,这些属性的位置就发生了变化,
其中:

(1) . sessionFactoryBeanName 还是在 OpenSessionInViewFilter里面,默认值也是 sessionFactory 如下图:


       (2) . singleSession 默认值也是 true

(3) . flushMode 属性来自于 Session 这个接口,默认值也是MANUAL【手动提交事务】。

它表示事务的提交方式,有如下几种:

优点:配置简单,

缺点:拦截了所有请求,效率不高,如果对象导航层级较多,会导致页面的加载速度变慢,延长了 Session的生命周期,加重了服务器的负担。

总结:

到最后推荐使用第二种,也就是局部取消延迟加载特性,灵活性更好。

解决no session问题的三种方式相关推荐

  1. $.ajax 加了headers报错_Springboot解决Ajax跨域的三种方式

    这篇文章不华丽,但比较实用,能解决不少大家实际业务中的问题.大家可以收藏起来,以备用时之需! 1.同源策略 1.1 含义 ajax出现请求跨域错误问题,主要原因就是因为浏览器的"同源策略&q ...

  2. AJAX异步请求解决跨域问题的三种方式

    一 什么是跨域 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说We ...

  3. JAVA解决生产消费者_Java常用三种方式解决生产者消费者问题(详细)

    package test; /** * Synchronized 版本解决生产者消费者 * wait() / notify()方法 */ import java.util.LinkedList; im ...

  4. vue 函数 路由跳转_vue中通过路由跳转的三种方式

    router-view 实现路由内容的地方,引入组件时写到需要引入的地方 需要注意的是,使用vue-router控制路由则必须router-view作为容器. 通过路由跳转的三种方式 1.router ...

  5. vbs执行ctrl+空格_VBS中解决路径带空格的三种方法

    vbs中,如果需要运行的程序中带有空格,按照通常的方式往往会提示错误,其实有两种形式不同的解决方法: 在应用程序前后分别加三个双引号,代码如下: Set wshell=CreateObject(&qu ...

  6. php支持链式操作,PHP三种方式实现链式操作-php教程

    正在php中有不少字符串函数,例如要先过滤字符串收尾的空格,再求出其长度,普通的写法是: strlen(trim($str)) 假如要完成相似js中的链式操作,比方像上面这样应该怎样写? $str-& ...

  7. .net session 有效时间_Python中requests模拟登录的三种方式(携带cookie/session进行请求网站)...

    这篇文章主要介绍了python中requests模拟登录的三种方式(携带cookie/session进行请求网站),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋 ...

  8. asp.net session 介绍一三种Session存储方式

    asp.net session 介绍一三种Session存储方式 www.firnow.com 时间:2009-03-04 作者:匿名 编辑:sky 点击: 1478 [评论] 对于asp.net的程 ...

  9. Spring 容器:三种方式解决 Resource leak: ‘applicationContext‘ is never closed 问题

    文章目录 前言 一.Spring 容器警告的产生 1.1.项目场景 二.Spring 容器未关闭后果分析 2.1.肉眼可见的警告 2.2.导致的内存泄漏 2.2.1.什么是内存泄漏? 2.2.2.如何 ...

最新文章

  1. Linux安装软件命令小结
  2. 川大优秀毕业生在GitHub上建了一个项目《深度学习500问》,还未完结就获赞无数
  3. 百度地图软件测试,使用 app-inspector 解析 i 调用百度地图定位的页面时 (iOS),会导致测试 app 崩溃...
  4. amount describe
  5. Linux 运维工具
  6. ug冲模标准件库_昆山兴模lt;携手gt;武汉益模,打通冲模“智能设计+精益管理”的最后一道关卡...
  7. amazeui学习笔记--css(常用组件1)--小徽章Badge
  8. U-GAT-IT整体流程分析
  9. “现男友”来了!荣耀手机正式官宣
  10. docker-compose的一些理解
  11. linux命令行使用
  12. Windows 10 20H2 微软MSDN官方正式版ISO镜像下载
  13. Pg Admin4 无法正常启动
  14. 自动驾驶应用加速 模拟仿真技术是关键之一
  15. CCF_Java_201909-3_字符画
  16. 《福州往事》(抒情散文)
  17. win 10 好吗?对比与ubuntu,对比于Mac呢?
  18. postman配置中文
  19. 关于nodebb中ns-custom-fields插件的使用
  20. mysql数据库快捷键_MySQL数据库(YOG软件)快捷键大全

热门文章

  1. xpath 爬取某网站图片
  2. Unity3D——AR小游戏
  3. 计算机专业初学者推荐书籍
  4. 目标检测中文类别--在图片中添加汉字
  5. 有没有测试水泥稳定性的软件,水泥稳定碎石基层的试验检测项目有哪些?急 急 急!!!...
  6. python物理建模初学者指南 pdf 脚本之家_[剑阁]上古卷轴5新手指南并行开坑版!...
  7. 分析报告 | 在线教育APP的市场到底有多大?
  8. Phaser 3 入门实例教程
  9. 光学载波网络(SONET OC)的网络带宽
  10. 在VM虚拟机上安装Red Hat Enterprise Linux