首先说明一下,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特定的查询方式。
当然这些弊端也幸好仅仅针对使用到需要解决延迟加载的时候触发。
经验分享,给大家提供多一套解决方案吧。鱼与熊掌,自己衡量使用。
相关推荐
Spring Boot强调“约定优于配置”,并支持热加载,便于开发过程中实时查看代码变更效果。 2. **Spring Cloud**: Spring Cloud是一系列框架的集合,用于在分布式系统中提供配置管理、服务发现、断路器、智能路由、微...
从技术角度分析,Spring框架的使用大幅降低了企业级应用开发的复杂性,Spring MVC作为Spring的一部分,将MVC模式引入到Spring框架中,使得Web层开发变得轻量且高效。MyBatis则通过简单的XML或注解方式配置,让开发者...
总的来说,解决`jlink v9 warning clone`问题需要对硬件、软件和开发环境有深入理解,通过排查硬件、更新固件和驱动、检查配置,以及参考社区经验,通常能有效解决问题。在处理这类问题时,耐心和细致是必不可少的,...
同时,查阅官方文档和社区论坛,看是否有其他用户遇到类似问题及解决办法。 总之,解决Jlink-clone问题的关键在于识别和替换问题组件。通过替换驱动和固件,我们可以优化克隆设备的性能,使其更接近原版J-Link的...
查询指令使用 JSON 形式的标记,可轻易查询文档中内嵌的对象及数组。 6. MongoDB 使用 update() 命令可以实现替换完成的文档(数据)或者一些指定的数据字段。 7. Mongodb 中的 Map/reduce 主要是用来对数据进行批量...
在整个固件修复和解决Clone问题的过程中,用户手册提供了详细的指导和操作说明。用户手册是帮助开发者正确操作Jlink v8的重要文档,通过手册中的指引,用户可以顺利完成固件的烧写和设备的调试。 总结来说,Jlink ...
在电子开发和嵌入式系统调试中,J-Link是一个非常常见的仿真器和编程器,它使得开发者能够通过USB接口连接到目标设备进行程序下载、调试和数据分析。然而,有时用户可能会遇到J-Link USB不被电脑识别或者显示“J_...
在使用高版本版KEIL时,提示要升级固件,升级后就出现JLINK is Clone的提示!“the emulator is JLink-Clone, the segger software only support orginal segger device” 然后闪退,IDE崩溃关闭! 解决方案: 1....
解决 JLINK 固件丢失或升级固件后提示 Clone 的问题 在使用 JLINK 仿真器进行单片机开发时,可能会遇到固件丢失或升级固件后提示 Clone 的问题,本文将提供解决该问题的步骤。 问题描述 使用 JLINK 仿真器时,...
标题中的“SpringMVC精品资源--Reddit clone built using Spring Boot, Sprin”表明这是一个使用Spring MVC、Spring Boot技术实现的Reddit克隆项目。这个项目可能是为了教学或实践目的,展示了如何利用Spring框架来...
标题 "spring_reddit_clone" 暗示我们正在讨论一个基于Spring框架的项目,它可能是对社交媒体平台Reddit的一个克隆实现。Spring是一个广泛使用的Java框架,尤其在开发企业级Web应用时,它提供了丰富的功能,如依赖...
使用socket.io + Vue + uni-app搭建的完整分离版客服系统,clone下来后安装必要依赖即可跑起来,功能众多,注释详细。 使用socket.io + Vue + uni-app搭建的完整分离版客服系统,clone下来后安装必要依赖即可跑...
使用maven tomcat7插件在嵌入式Apache Tomcat Web容器中运行应用程序 加载应用程序后,导航至: http://localhost:8080/online-application/login 可以在Spring的application-security.xml配置文件中找到一些示例...
spring-boot-starter-diamond将diamond集成到springboot中使用,spring-boot-starte构件。spring-boot-starter-diamond,让你可以使用spring-boot的方式开发diamond程序。使diamond开发变得如此简单。让你可以使用...
后端有两个版本:SpringBoot 版本和 SpringCloud 版本。 1.主要依赖 名称 版本 描述 Angular 16.2.0 Angular 核心库。 PrimeNG 16.2.0 开源组件库。 Bootstrap 5.2.3 响应式布局。 ngx-bootstrap 11.0.2 基于 ...
Spring Cloud Config 使用基于VCS的backend来存储配置信息,在默认情况下,配置信息会被checkout或clone到本地文件系统的临时目录中,例如在Linux系统中,可能是 `/tmp/config-repo-<randomid>`。但是,这些临时...
在本文中,我们将详细介绍如何使用 IDEA 和 Gradle 构建 Spring 源码环境,以便深入学习 Spring 源码。下面是具体的步骤和知识点总结。 一、下载 Spring 源码 下载 Spring 源码有两种方式:一种是直接下载 zip ...
谷粒学院全栈开发项目 GitHub 项目下载 ...除此之外,项目中使用了阿里巴巴的EasyExcel实现对Excel的读写操作,使用了Redis进行首页数据的缓存,使用Git进行代码的版本控制,还整合了Swagger生成接口文档 。
它是一个回购系列的一部分,该系列旨在使用Angular创建渐进式Web应用程序 Web应用程序实时演示 快速开始 # choose a repo # download the example or clone the repo from github git clone ...
react-redux-rxjs-starter-kit一个集成React全家桶的脚手架,主要技术栈:react16 + routerV4 + redux + webpack3 + redux-observable + rxjs + scss + less + css modules + react-hmre + eslint + 组件异步加载 + ...