早期的项目配置如下:
<bean id="dataSourceProxy" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> <property name="targetDataSource" ref="dataSource" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSourceProxy" /> ... </bean>
与此同时,项目中使用了apache shiro,当我在controller中使用了类似“@RequiresRoles”之类的方式要求做授权时,我的自定义Realm中的doGetAuthorizationInfo方法会报错(不同的数据源,报错可能不同),当使用dbcp时报如下异常:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:No operations allowed after connection closed.
后来注意到是在doGetAuthorizationInfo中多次调用service引起的,对,是多次调用才会引起,如果在该方法中只调用一次service,则不会报异常,当时为了找问题,在Realm中另一个用于登录验证的“doGetAuthenticationInfo”方法中也进行了多次调用service的尝试,什么问题也没有发现,也更换过不同的数据源,没有作用,所以估计问题可能在配置上。
经过排查配置文件,发现一直是在用TransactionAwareDataSourceProxy,后来在entityManagerFactory中改为直接使用未包装的dataSource,发现问题已经得到解决,原因似乎是在JPA下并没有使用“TransactionAwareDataSourceProxy”的必要性,不然的话还会因此带来一些问题。
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> ... </bean>