首页 > 代码库 > Spring webflow + Jpa + Hibernate运行时无响应问题处理
Spring webflow + Jpa + Hibernate运行时无响应问题处理
问题现象:
使用Spring webflow过程的页面需要从Mysql查询数据,在前台展现出来,在查询几次后页面就没有响应,服务器的日志最后一条就是Hibernate的SQL语句。
运行环境:
JRE:1.8
Spring framework:4.3.8.RELEASE
Spring webflow:2.4.5.RELEASE
Spring data jpa:1.11.4.RELEASE
Hibernate:5.2.5.Final
MySql:5.7.14
Tomcat:8.0(使用tomcat的数据库连接池)
问题解决过程:
1. 怀疑数据库死锁
开发环境只有一个用户,并且这些页面的操作只有查询,并在用Mysql workbench登录查询同一个表的记录正常,所以排除这种可能性
2. 可能是自身对webflow中使用jpa的方法没有理解,所以做一些尝试:
- 查看《spring in action》、《spring web flow权威指南》,都没有对在web flow中使用持久化的说明
- 查看spring官网的webflow,对于Flow Managed Persistence的说明,主要实现一个流操作中的数据持久化和事务。每一次进入一个flow时会启用一个新的持久化上下文,并且在mysql后台看到会增加一个客户端连接,这个连接应该要等这个flow被commit后才会释放。
这里有2个疑问:
* 为什么每一个flow进入时会打开一个新的数据库连接,理论上Hibernate的Session管理机制会创建一个新的session?
* 这个flow如果没有被完整执行,也就是中途退出了,那么这个持久化上下文只能等到连接超时才能释放,如果高并发那很快会挂掉,如何处理?
3. 验证
将连接池的最大连接数改成5个,通过点击页面,到第6个页面时就会挂住没有响应,因为拿不到连接10s后超时报错,此时如果连接池设置中没有加maxWaitMillis="10000"那么会一直等待,这个现象会让人无从入手调查,这点大家要注意
<Context> <Resource name="jdbc/pt" type="javax.sql.DataSource" auth="Container" maxTotal="5" maxIdle="30" maxWaitMillis="10000" driverClassName="com.mysql.jdbc.Driver" username="pt" password="pt123" url="jdbc:mysql://127.0.0.1:3306/pt" /> </Context>
4. 解决
尝试去除webflow的<persistence-context/>标签,数据的一致性交给service处理
去除后页面上从后台数据库查询记录正常,但当选定查询结果中的某一个记录跳转到下一个页面时(选定的记录ID作为request parameters传到flow的Action,由Action调用service层再调用dao层加载这个记录的具体信息),报错:
org.hibernate.LazyInitializationException: could not initiali
dao层是继承了Spring的JpaRepository类,加载时调用getOne方法,查看getOne的javadoc,See Also:EntityManager.getReference(Class, Object)
对象是延迟加载的。
换成CrudRepository类的findOne方法后可以正常显示数据。
问题解决!
Spring webflow + Jpa + Hibernate运行时无响应问题处理