首先说明一下,hibernate的延迟加载特性(lazy)。所谓的延迟加载就是当真正需要查询数据时才执行数据加载操作。因为 hibernate当中支持实体对象,外键会与实体对象关联起来。如果没有这一特性,当查询某一个含有外键的实体对象时,hibernate会把其他实体对象的数据都查询出来。
简单的来说,当你想查询某个对象时,实际上调用了多条查询语句。有了延迟加载特性,就避免了这种情况的发生,当你真正的使用get另外一个实体对象时,才再执行下面一条查询语句。
但有些时候,这个特性却会给我们应用中带来一些问题。
这个问题相信大家并不陌生了,hibernate的延迟加载(lazy)特性的确不错的优点,如果没了这个特性,我相信大家在处理一些外键的对象时会头大起来,因为效率十分的低。甚至很多人都觉得使用jdbc要比hibernate要高效甚至方便得多,而迫使不去使用hibernate。
我想说,没错,使用jdbc在效率上的确可能要快许多,但差距也不会太大的,因为hibernate本身就支持多种查询方式,SQL、HQL、 DetachedCriteria等。而相反的,hibernate在维护性上比jdbc强很多,因为是实体对象的关系。我相信如果您使用过jdbc来实现注册功能的话,会深有体会。
提示session已关闭(no session or session was closed)
触发这个问题的原因在于,hibernate在查询操作完毕的时候会自动的把session关闭掉,为了降低使用的资源。但问题也这样产生了,不要忘了之前所说的hibernate特性,此时再调用get实体方法的时候就会有可能出现这个错误。因为session已经关闭而不能继续执行查询了。
解决思路:
1、关闭延迟加载特性。
操作起来比较简单,因为hibernate的延迟加载特性是在hbm配置里面可控制的。默认lazy="true",具体配置可以查看一下相关文档,就不详细叙述了。
但使用这个解决办法带来的隐患是十分大的。
首先,出现no session or session was closed就证明了您已经在使用外键关联表,如果去掉延迟加载的话,则表示每次查询的开销都会变得十分的大,如果关联表越多,后果也可以想象得到。所以不建议使用这个方法解决。
2、在session关闭之前把我们想要查询的数据先获取了。
首先需要了解一下session什么时候关闭,也就是它的生命周期。通常情况下hibernate会在查询数据关闭session,而使用getHibernateTemplate().get方法查询后会延迟关闭的时间。会在事务结束后才关闭。
使用拦截器(Interceptor)或过滤器(Filter)控制session。
spring为解决hibernate这一特性提供的解决方案,可以有效的控制session生命周期。
使用这两个方法的详细描述就不多介绍了网上也有不少的文章。这里主要是介绍自己的一套方案。
使用CLONE解决延迟加载问题。
使用Interceptor和Filter,弊端是所有session都一概而论了,无论是否需要延迟session关闭都统统把session关闭的时间延迟了。这里带来了一些资源开销的问题,虽然没必要这么钻牛角尖。但也只是继续本着研究的精神吧。这里的影响程度也是有级别的,因为控制在业务层或者是视图层,影响也有不同的。还有的时候会与其他集成框架冲突,例如又用了spring的security框架,貌似会有些冲突发生。
在这里想了一下有没有更好的解决办法呢?能在我们需要的时候把数据获取掉,而又不会出现session关闭的情况。
这时我想到了两点,第一,findById方法时候的session会延迟。第二,clone方法。
对于第一点,只能使用get方法来实现也不是绝对的,我们也可以使用DetachedCriteria查询。
第二点有些朋友有些疑问或者陌生,稍微讲解一下。
为什么使用clone?
因为在session关闭之前使用get实体获取的对象没错你也可以查询得到,但是session关闭后,这些数据就不能访问了。如果直接赋值结果还是一样的,因为只是址传递,所以我们必须使用clone方法来把获取后的数据做拷贝操作,而必须还是deep clone,shadow clone也是不行的。
具体操作
1、实现Cloneable接口。
因为我们要进行deep clone操作,所以BO对象必须作以下操作。
implements Cloneable
2、重写(override)clone方法。
clone方法默认为
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
要进行deep clone操作必须把protected改为 public,并且把返回的object改为具体的Bean对象。
3、执行clone操作。
首先,前提当然是确保事务结束之前session未被关闭,可以使用get实体的操作。
然后看下面例子
public List<AccAlias> listAccAlias() {
List<AccAlias> all = AccAliasDAO.findAll();
if (all != null && !all.isEmpty())
for (AccAlias accAlias : all) {
try {
Mailbox mailbox = accAlias.getMailbox();
if(mailbox!=null){
mailbox = mailbox.clone();
accAlias.setMailbox(mailbox);
}
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
return all;
}
后续问题研究:
姑且作为一个比较非主流的解决方案吧,是否适合还是要看大家需求的,没有一套方案是绝对适合的。
使用clone解决延迟加载的弊端:
1、clone的实际开销。
2、查询方式的依赖性。必须根据ID查询方式来查询实体。而且更可以认为耦合度提高了,因为业务层clone操作有时必须依赖DAO特定的查询方式。
当然这些弊端也幸好仅仅针对使用到需要解决延迟加载的时候触发。
经验分享,给大家提供多一套解决方案吧。鱼与熊掌,自己衡量使用。
分享到:
相关推荐
这是一个工作模板项目,它展示了一个示例多层 J2EE Web 应用程序,其中包含Apache Wicket 、 Spring IoC 、 JPA/Hibernate集成和基于Bootstrap的前端。 它演示了MvC 、 SoC 、 IoC 、 DAO 、 Service layer和Open ...
156、在jsp:useBean语法中使用beanName有何好处? 37 157、当我使用时,在浏览器的地址栏没有改变? 37 158、如何转换JSP 0.9版本的文件到JSP1.1? 37 160、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么...
面试中会讨论如何使用Spring Boot构建应用,以及Spring Cloud的组件功能和应用场景。 【Hibernate/MyBatis】 Hibernate是ORM(对象关系映射)框架,自动管理数据库操作。MyBatis则是轻量级的持久层框架,允许...
Spring 可以管理 Hibernate 的 SessionFactory,提供事务管理,并集成 Hibernate 的 DAO 支持。 #### 57. doGet()和doPost()作用,有什么区别? - **doGet**:处理 GET 请求,通常用于检索数据。 - **doPost**:...
- **知识点概述**:Hibernate是一个全功能的ORM(Object-Relational Mapping)解决方案,能够将Java对象映射到数据库表中。 - **教师**:未指定 - **教学目标**: - 学习Hibernate的核心概念,如Session、...
Java编程语言在软件开发中占有重要地位,尤其在企业级应用中广泛使用。这份"java笔试题.pdf"包含了多个常见的Java编程题目,涵盖了字符串操作、正则表达式、日期格式化、进制转换以及Java核心概念等多个方面。下面将...
开发者需熟悉MVC(Model-View-Controller)模式,理解RESTful API设计原则,并能使用ORM(对象关系映射)工具如Hibernate或SQLAlchemy进行数据库操作。 3. **数据库管理**:MySQL、PostgreSQL或MongoDB等数据库用于...
了解如何使用IDE(如Eclipse、IntelliJ IDEA)的调试功能,以高效定位和解决问题。 9. **持续集成/持续部署(CI/CD)**:了解Jenkins、GitLab CI/CD等工具,自动化构建、测试和部署过程,提升开发效率和产品质量。 ...
Spring、Spring Boot、Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis、JVM优化等都是Java开发中常用的框架和工具,它们各自在不同层面提供了强大的功能和性能优化。 以上仅是部分...
JavaWeb校园订餐系统项目源码是一个典型的基于Java技术栈的Web应用,旨在解决校园内的餐饮预订需求。这个系统可能包含前端用户界面、后端服务器处理逻辑以及数据库交互等核心模块,为学生、教师和其他校园内人员提供...
- 加载整个文档到内存中,然后提供API进行访问和修改。 - 适用于小文件。 - **SAX (Simple API for XML)**: - 逐行读取文件,事件驱动,适用于大文件。 - **StAX (Streaming API for XML)**: - 基于事件驱动的模型,...
9、hibernate中的update()和saveOrUpdate()的区别,session的load()和get()的区别。 122 10、简述 Hibernate 和 JDBC 的优缺点? 如何书写一个 one to many 配置文件. 122 11、iBatis与Hibernate有什么不同? 122 12、...
9、hibernate中的update()和saveOrUpdate()的区别,session的load()和get()的区别。 122 10、简述 Hibernate 和 JDBC 的优缺点? 如何书写一个 one to many 配置文件. 122 11、iBatis与Hibernate有什么不同? 122 12、...
9、hibernate中的update()和saveOrUpdate()的区别,session的load()和get()的区别。 122 10、简述 Hibernate 和 JDBC 的优缺点? 如何书写一个 one to many 配置文件. 122 11、iBatis与Hibernate有什么不同? 122 12、...
9、hibernate中的update()和saveOrUpdate()的区别,session的load()和get()的区别。 122 10、简述 Hibernate 和 JDBC 的优缺点? 如何书写一个 one to many 配置文件. 122 11、iBatis与Hibernate有什么不同? 122 12、...
9、hibernate中的update()和saveOrUpdate()的区别,session的load()和get()的区别。 122 10、简述 Hibernate 和 JDBC 的优缺点? 如何书写一个 one to many 配置文件. 122 11、iBatis与Hibernate有什么不同? 122 ...
9、hibernate中的update()和saveOrUpdate()的区别,session的load()和get()的区别。 133 10、简述 Hibernate 和 JDBC 的优缺点? 如何书写一个 one to many 配置文件. 133 11、iBatis与Hibernate有什么不同? 133 12、...
9、hibernate中的update()和saveOrUpdate()的区别,session的load()和get()的区别。 122 10、简述 Hibernate 和 JDBC 的优缺点? 如何书写一个 one to many 配置文件. 122 11、iBatis与Hibernate有什么不同? 122 12、...
JSP中有九个内置对象:`out`、`page`、`pageContext`、`request`、`response`、`session`、`application`、`config`、`exception`。 3. **描述一下JSP中taglib的用法?** `...
Java语言是软件开发领域广泛使用的编程语言,尤其在企业级应用中占据着核心地位。以下是一些Java面试中常见且重要的知识点详解: 1. 访问修饰符:`public`、`protected`、`private`和`final` - `public`:任何类都...