首页 > 代码库 > 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运行时无响应问题处理