我有以前struts+hibernate的一些代码。现在想加入spring,但是既然spring是为了分离程序间的耦合,当然,也不能和spring结合的太紧蜜。
所以,我尽量不在manager和DAO里使用spring的类。于是写了下面的几个基础类,希望以后即使修改也不用改动太大。
public interface BaseDAO {
public Long add(Object object) throws HibernateException;
}
public class BaseDAOImpl extends HibernateDaoSupport {
//这里是希望spring在构造这个类时将sessionFactory传递给HibernateDaoSupport.setSessionFactory(),并初始化一个session对象
protected Session session =null;
public BaseDAOImpl(SessionFactory sessionFactory) {
this.setSessionFactory(sessionFactory);
this.session = this.getSession();
}
public Long add(Object object) throws HibernateException{
Long reval=null;
reval=(Long)session.save(object);
return reval;
}
public interface BaseManager {
public Long add(Object object) throws BusinessLogicException, HibernateException;
}
public class BaseManagerImpl {
}
具体的UserDAO和UserManager如下:
public interface UserDAO extends BaseDAO{
}
public interface UserManager extends BaseManager{
}
public class UserDAOImpl extends BaseDAOImpl implements UserDAO{
}
public class UserManagerImpl extends BaseManagerImpl implements UserManager{
public Long add(Object object) throws BusinessLogicException, HibernateException {
return userDAO.add(object);
}
}
spring配置文件如下:
<beans>
<description>bean test</description>
<bean id="hibernateSessionFactory" factory-method="getSessionFactory"
class="huye.common.util.HibernateUtil" />
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="hibernateSessionFactory" />
</property>
</bean>
<bean id="UserDAO" class="huye.user.proxy.impl.UserDAOImpl">
<constructor-arg><ref local="hibernateSessionFactory"/></constructor-arg>
</bean>
<bean id="UserManagerTarget" class="huye.user.proxy.impl.UserManagerImpl">
</bean>
<bean id="UserManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="hibernateTransactionManager" />
</property>
<property name="target">
<ref local="UserManagerTarget" />
</property>
<property name="proxyTargetClass">
<value>false</value>
</property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
<prop key="update*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
<prop key="delete*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
<prop key="get*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
</props>
</property>
</bean>
</beans>
然望能通过这样的结构达到即使以后去掉了spring,我只需要修改baseDAOImpl和BaseManagerImpl类就可以了。
可是运行后发现事务没有提交,但也不出现错误提示。
连续试验了一天,并使用sqlserver事件查看器,才发现问题。原来,add时同时建立了两个连接,连接1没有执行SQL语句,但提交了事务,连接2只执行了SQL语句。
可能是因为我把sessionFactory放在了DAO的构造方法里,而不是setter里。
把BaseDAOImpl改造一下,构造方法去掉,加入
public void setSessionFactory2(SessionFactory sessionFactory){
this.setSessionFactory(sessionFactory);
this.session = this.getSession();
System.out.println("session=" + session);
}
并在spring配置文件里做相应配置。
这次发现虽然和数据库只建立了一个连接,但是却没有执行SQL语句。
奇怪了。
把add方法改一下:
public Long add(Object object) throws HibernateException{
Long reval=null;
reval=(Long)getSession().save(object);
return reval;
}
这次才成功,数据正确保存。
但是这样的话,我所有的DAO都要把session.method改成getSession().method。
这也太麻烦了。
只是很奇怪,明明只有一个session,不知道为什么不执行呢?
等下次解决吧。