dao注入的sessionFactory和hibernateTemplate丢失

版本

整合SSH

struts版本: 2.5.14

spring版本: 5.0.3.RELEASE

hibernate版本: 5.2.13.Final

jdk版本: 1.8

数据库使用MySql

现象:

IDEA整合SSH的时候:突然遇到dao下的getHibernateTemplate()为null,

打入断点后我发现HibernateDaoSupport的setSessionFactory()已被调用。spring 已注入sessionFactory,而继承HibernateDaoSupport的HibernateDAO在当时存在hibernateTemplate。等到spring加载完applicationContext.xml之后,调用getHibernateTemplate()返回值却为null.

缘由:

花费大半天时间我才发现原来是<aop:pointcut>属性设置的原因.我将切点匹配的范围设置的太大了导致前面的dao的bean被重新装配(sessionFactory未注入)

出错的applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
">

<!-- 自动扫描与装配bean,包括子包 -->
<context:component-scan base-package="com.arthur.web.*"/>
<!-- 导入外部的properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!--配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<!--数据库驱动类-->
<property name="driverClass" value="${driverClass}"/>
<!--数据库连接URL-->
<property name="jdbcUrl" value="${jdbcUrl}"/>
<!--数据库用户名-->
<property name="user" value="${user}"/>
<!--数据库用户密码-->
<property name="password" value="${password}"/>
<!--连接池最小保留个数-->
<property name="minPoolSize" value="5"/>
<!--连接池最大保留个数-->
<property name="maxPoolSize" value="30"/>
<!--初始化时获得的连接数-->
<property name="initialPoolSize" value="10"/>
<!--最大空闲时间,为0即永不连接-->
<property name="maxIdleTime" value="60"/>
<!--当连接池连接耗尽时,一次性获取的连接数-->
<property name="acquireIncrement" value="5"/>
<!-- 控制数据源内加载的PreparedStatements数量。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:0 -->
<property name="maxStatements" value="8"/>
<!-- maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default:0 -->
<property name="maxStatementsPerConnection" value="5"/>
<!--每60检查连接池中所有的空闲连接-->
<property name="idleConnectionTestPeriod" value="60"/>
<!--和数据库连接失败后请求重新连接的次数-->
<property name="acquireRetryAttempts" value="30"/>
<!--连接失败会通知等待的数据源连接放弃连接,数据源仍保留-->
<property name="breakAfterAcquireFailure" value="true"/>
</bean>

<!--定义Hibernate的SessionFactory -->
<!-- SessionFactory使用的数据源为上面的数据源 -->
<!-- 指定了Hibernate的映射文件和配置信息 -->
<!--session工厂的配置-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!--为session工厂注入数据源-->
<property name="dataSource" ref="dataSource"/>
<!--为hibernate配置部分属性-->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="show_sql">true</prop>
<prop key="format_sql">true</prop>
<prop key="hbm2ddl.auto">update</prop>
<prop key="hibernate.connection.url">jdbc:mysql://localhost:3306/myweb</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
</props>
</property>

<property name="mappingLocations">
<list>
<value>classpath:com/arthur/web/pojo/*.hbm.xml</value>
</list>
</property>
<property name="annotatedClasses">
<list>
<value>com.arthur.web.pojo.User</value>
</list>
</property>

</bean>

<!-- dao实例化 -->
<bean id="hibernateDAO" class="com.arthur.web.core.common.dao.HibernateDAO">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


<!--配置事务管理-->
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置事务增强 -->
<tx:advice id="txAdvice" transaction-manager="txManager" >
<tx:attributes>
<tx:method name="do*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>

<!-- 配置将通知织入目标对象-->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut expression="execution(* com.arthur.web..*.*(..))" id="txPc"/>
<!--定义通知-->
<aop:advisor pointcut-ref="txPc" advice-ref="txAdvice"/>

</aop:config>

</beans>

解决方案:

当我将切点匹配范围收缩到service范围时候。dao恢复正常可以进行增删改查

<aop:pointcut expression="execution(* com.arthur.web.service..*.*(..))" id="txPc"/>

待解决疑问:

为啥 aop:pointcut 设置范围过大的时候重装配的dao未注入session.由于花费太长时间在这问题上,这疑问只能留到以后再处理了了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章