关于spring事务管理不关闭connection问题!多谢。

07-02-04 qujingbo
              

项目使用hibernate 2.0,spring 1.2.8,struts

问题在于连接很快就被占满,怀疑PSRING没有管理连接,仔细查看LOG发现,会有些warn提示unclosed session.在网上查了些资料,资料显示若在DAO中使用getHibernateTemplate().*时,spring会自动管理session(包括connection),而强制使用getSession()时时spring是不管理session的。而项目中大量使用这种代码,如下:

Session session = this.getSession();

// 拼装hql

String queryStr = "from DyDutyGroup dyDutyGroup where dyDutyGroup.isChange="

+ Constants.GROUP_IS_NOT_CHANGE

+ " AND PID IS NOT NULL and pid in "

+ "(select dyUser.dutyGroupId from DyUser dyUser where dyUser.userId = '"

+ userId + "'" + "and dyUser.isManager = 1" + ")";

Query query = session.createQuery(queryStr);

// 当前页通过每页数*当前页数取得要取记录的行数

query.setFirstResult(pageSize.intValue() * curPage.intValue());

// 取pageSize条

query.setMaxResults(pageSize.intValue());

java.util.List result = query.list();

其中这行Session session = this.getSession();正如资料显示,spring是不进行session管理的。资料显示需要手动关闭。

finally {

this.closeSessionIfNecessary(session);

}

这时,我做了试验,在使用getSession()方法中添加closeSessionIfNecessary(session)关闭session方法。有此方法会关闭,而有些又是报错,提示session is colsed。郁闷至极。

              

2
qujingbo
2007-02-04 21:27

项目中在web.xml中配置OpenSessionInViewFilter。而applicationContext的加载方式我使用的是struts的plugin方式配置ServiceLocator,通过ServiceLocator.getInstance().getBean()方式取得bean.这里就有问题了,OpenSessionInViewFilter是setAttribute()一个context,而我并没有使用spring的Action的支持获取Context,而是通过ServiceLocator中的factory = new ClassPathXmlApplicationContext(fn);方式加载context,这时OpenSessionInViewFilter会管理session吗?也就是说OpenSessionInViewFilter会生效吗?我的lazy暂时是fasle。

我的疑惑在,如果我调用getSession(),spring是否真的不会管理session,是否需要手动关闭。若真需要手动关闭,那问题就有了,我显示的使用this.closeSessionIfNecessary(session);关才SESSION,为什么提示session is closed,是spring container在管理session吗?

具体spring事务配置如下:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName">

<value>${hibernate.connection.driver_class}</value>

</property>

<property name="url">

<value>${hibernate.connection.url}</value>

</property>

<property name="username">

<value>${hibernate.connection.username}</value>

</property>

<property name="password">

<value>${hibernate.connection.password}</value>

</property>

</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">

<property name="hibernateProperties">

<props>

<prop key="hibernate.dialect">net.sf.hibernate.dialect.Oracle9Dialect</prop>

</props>

</property>

<property name="dataSource">

<ref bean="dataSource"/>

</property>

<property name="configLocation">

<value>classpath:hibernate.duty.xml</value>

</property>

</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">

<property name="sessionFactory">

<ref local="sessionFactory"/>

</property>

</bean>

<bean id="dyDutyConfigRuleDao"

class="com.boco.eoms.subsystem.duty.dao.impl.DyDutyConfigRuleDaoImpl">

<property name="sessionFactory">

<ref bean="sessionFactory" />

</property>

</bean>

<bean id="dyDutyConfigRuleBO"

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<property name="transactionManager">

<ref bean="transactionManager" />

</property>

<property name="target">

<ref local="dyDutyConfigRuleTarget" />

</property>

<property name="transactionAttributes">

<props>

<prop key="addDyDutyDateConfigRule">

PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-Exception

</prop>

<prop key="updateDyDutyDateConfigRule">

PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-Exception

</prop>

<prop key="addDyDutyDateConfigRuleByPeriods">

PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-Exception

</prop>

<prop key="updateDyDutyDateConfigRuleByPeriods">

PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-Exception

</prop>

</props>

</property>

</bean>

有时还会出现这个问题,在一个人登陆后,退出重新登陆时,就会出现如下错误。

00:42:22,302 ERROR JDBCExceptionReporter:38 - Cannot open connection

java.sql.SQLException: ORA-01017: invalid username/password; logon denied

at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)

at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289)

at oracle.jdbc.ttc7.O3log.receive1st(O3log.java:407)

at oracle.jdbc.ttc7.TTC7Protocol.logon(TTC7Protocol.java:259)

at oracle.jdbc.driver.OracleConnection.<init>(OracleConnection.java:346)

at oracle.jdbc.driver.OracleDriver.getConnectionInstance(OracleDriver.java:468)

at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:314)

at java.sql.DriverManager.getConnection(DriverManager.java:512)

at java.sql.DriverManager.getConnection(DriverManager.java:140)

at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:291)

多谢。祝好~~~~~~~~~

banq
2007-02-05 16:00

直接调用getSession()肯定是不推荐的,可使用getHibernateTemplate().getSession,

Spring的Session是一个thread-bound Session ,就是说它是和某个线程绑定的,而这个线程往往就是承载Servlet/Jsp的那个线程,实际意思就是其生命周期scope是request/response的。所以和Servlet的context无关。

强制通过getSession()获得的Hibernate Session, 这个session可能是当前事务中之前打开的用过的那个Session,或者可能是一个新的,如果你需要必须是新的,那么通过你引用的那个HibernateTemplate中 的allowCreate为true!采取这个方案可以解决你connection关闭的错误。

qujingbo
2007-02-06 11:07

谢谢banq,连接问题已解决。

现在我觉得OpenSessionInViewFilter问题很多,我使用ServiceLocator方式加载,filter也不起作用。所以想问可lazy怎么解决。十分感谢。

感谢banq

banq
2007-02-09 16:34

想激活lazy,目前我也只知道只能采取OpenSessionInView模式,而这个模式弊病很多,我以前帖子批判过。

这个基本问题必须由他们作者亲自来解决,可以说是一个原罪。

2Go 1 2 下一页