MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法

 

用 MyEclipse 的自动生成功能产生的 Spring + Hibernate 的 DAO 有时候会出现不能保存数据但是可以查询数据的问题, 这是因为默认生成的 Spring 配置文件里面没有包含对事务的操作, 也就是没有 commit Hibernate transaction 的调用所以无法保存数据. 也就是正确的调用需要 beginTran, save, commit, 但是现在就少了 tran 的调用代码部分. 因为刚刚接触 Spring 这个 "轻量级" 非侵入框架不久, 所以好多问题不是太熟悉, 最近收集了一些资料看了看总算解决了问题. 有问题不要紧, 只要能通过学习来解决它就可以了, 我个人并不很喜欢没事去精通 XXX 框架, 而是喜欢做一些解决问题和查资料能力的锻炼, 有了后面所提的能力, 不管改天是不是出了个 Winter 框架, 也不会担心落伍, 当然前提是基础知识要牢固, 否则很容易看不懂.

解决方法是在配置文件里"侵入性"(必须这样做, 做额外的配置和修改, 否则就无法正常工作, 所以是侵入性的)的加入事务配置后就可以正常的保存数据到 Derby, Oracle 等数据了, 也有其它的解决办法, 希望用 Spring 比较早的经验多的人提出建议:

1. 用 Ecipse 的重构给自动生成的 UsersDAO 类添加一个接口, 里面包含所有的方法声明, 例如 IUsersDAO, 加入接口的目的是为了使用 JDK 的动态代理方式实现的 Spring AOP 来工作, 也有另一种解决方案使用 CGLIB 的话就不需要这一步了, 这种方式下一次讨论.

public interface IUsersDAO {

 public abstract void save(Users transientInstance);
}

public class UsersDAO extends HibernateDaoSupport implements IUsersDAO {
...
 public void save(Users transientInstance) {
  log.debug("saving Users instance");
  try {
   getHibernateTemplate().save(transientInstance);
   log.debug("save successful");
  } catch (RuntimeException re) {
   log.error("save failed", re);
   throw re;
 }
...
}

2. 修改配置文件给原来的 UsersDAO 加入代理类来进行事务管理:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">


 <bean id="sessionFactory"
  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="configLocation"
   value="file:src/hibernate.cfg.xml">
  </property>
 </bean>

 <!-- UsersDAO implements IUsersDAO 接口 -->
 <bean id="UsersDAO" class="dao.UsersDAO">
  <property name="sessionFactory">
   <ref bean="sessionFactory" />
  </property>
 </bean>

 <!-- 以下两个 Bean transactionManager 和 userDAOProxy 是新加入的内容, 用来配置事务 -->


 <!-- 声明一个 Hibernate 3 的 事务管理器供代理类自动管理事务用 -->
 <bean id="transactionManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory">
   <ref local="sessionFactory" />
  </property>
 </bean>

 <!-- 这个代理类是最后对外公开的类, 否则因为没有进行事务操作,
 保存时没有提交 hibernate 的事务, 这将无法对数据库进行改动, 也就是原来要调用 UsersDAO 的地方都要转而调用这个代理对象 userDAOProxy; 具体的属性配置在 target 参数那里指定了这个对象对原来的 UsersDAO 对象进行代理;
 也因为要使用动态代理, 所以这里必须给 UsersDAO 抽象一个接口 IUsersDAO, 只有通过它来作为原来配置的 UsersDAO 的代理工作, 才能让 Spring 在保存数据的时候自动打开 Hibernate 的 Transaction 并提交, 即属性 transactionManager 配置的 HibernateTransactionManager -->
 
 <bean id="userDAOProxy"
  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  <property name="transactionManager">
   <ref bean="transactionManager" />
  </property>
  <property name="target">
   <ref local="UsersDAO" />
  </property>
  <property name="transactionAttributes">
   <props>
    <!-- 这里的方法签名可以精确到方法, 先懒惰一下全配置上 -->
    <prop key="*">PROPAGATION_REQUIRED</prop>
   </props>
  </property>
 </bean>

 

</beans>

3. 修改调用代码, 原来调用 UsersDAO 的地方都要转而调用 userDAOProxy, 而且转换后的目标要修改为 IUsersDAO, 否则就会报 ClassCastException, 具体原因参考 Spring 的 AOP 实现部分的内容, 也可以用 cglib 来解决.
  原始代码:
  UsersDAO dao = applicationContext.getBean("UsersDAO");
  dao.save(users);// 可能无法保存数据, 因为没有事务管理
  修改为:
  IUsersDAO dao = applicationContext.getBean("userDAOProxy");
  dao.save(users);// 现在应该 OK 了, 因为事务提交了

posted on 2007-08-07 08:49 BeanSoft 阅读(3066) 评论(15)   编辑   收藏 所属分类: Spring
<script type=text/javascript> // </script>
Comments
    #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法
静儿
Posted @ 2007-08-07 13:32
呵呵,说的很详细啊。  回复  更多评论   
  • #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法
    开机
    Posted @ 2007-08-07 19:13
    我在hibernate 和spring_hibernate生成的DAO里面没有找到Transaction有关的东东,Transaction是不是隐藏在这些DAO所引用的一个类里面?  回复  更多评论   
  • #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法
    BeanSoft
    Posted @ 2007-08-07 19:57
    是的, Spring 加入事务必须通过配置文件后才可以.  回复  更多评论   
  • #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法
    开机
    Posted @ 2007-08-07 20:20
    看了spring aop后,发现自己刚才说的有问题。原来spring通过代理,可以自动加入transactionManager.
    不要见笑我这个初学者。
    以后还要多多指教。  回复  更多评论   
  • #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法
    BeanSoft
    Posted @ 2007-08-07 20:49
    呵呵, 大家都是初学者, 千万不要有这样的心理负担, 共同进步!  回复  更多评论   
  • #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法
    IDreamer
    Posted @ 2007-08-08 00:31
    在我了解就然有持久化数据那种类库之前,我设计的项目苦苦的写了100多条SQL语句和10几个数据库实体类。。。

    如今知道了,学习Hibernate还不晚,不过可能先看看TopLink可能更简单吧  回复  更多评论   
  • #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法[未登录]
    wind
    Posted @ 2007-08-10 00:10
    使用SSH+derby开发
    我用了声明式事务 但是依然不能保存数据 出现
    org.springframework.jdbc.BadSqlGrammarException: Hibernate operation: could
    not get or update next value; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException:
    Schema 'WIND' does not exist
    错误 为什么啊   回复  更多评论   
  • #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法[未登录]
    wind
    Posted @ 2007-08-10 00:11
    我用的自动代理
    <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames">
    <value>*DAO</value>
    </property>
    <property name="interceptorNames">
    <list>
    <value>transactionInterceptor</value>
    </list>
    </property>
    </bean>  回复  更多评论   
  • #  re: MyEclipse生成的Spring+Hibernate无法保存数据问题的解决方法[未登录]
    Dreamer
    Posted @ 2007-08-10 15:12
    只要在
    hibernate.cfg.xml
    加入
    <property name="connection.autocommit">true</property>  回复  更多评论  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值