spring配置如下:
<bean  id= "proxoolDataSource " class= "org.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property  name= "driverClassName"> 
            <value>org.logicalcobwebs.proxool.ProxoolDriver</value> 
        </property> 
        <property name="url"> 
            <value>proxool.insuranceAgentPool</value> 
        </property> 
    </bean>
    <bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" >
      <ref bean="proxoolDataSource" />
    </property>
  </bean>
  <bean id="businessProxy"
     class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager">
       <ref bean="transactionManager" />
    </property>     <property name="target">
       <ref bean="userService" />
    </property>
    <property name="transactionAttributes">
      <props>
                          <!--这个地方不管我怎么配置,当操作数据库时,事务总是被提交 -->
         <prop key="add*">PROPAGATION_REQUIRED</prop>
      </props>
    </property>
  </bean>dao 的配置
<bean id="userDao" class="insurance.agent.dao.impl.UserDaoImpl">
<property name="dataSource">
<ref bean="proxoolDataSource"></ref>
     </property>
</bean>java dao类:
public class UserDaoImpl extends JdbcDaoSupport implements IUserDao {
   public static final String CREATE_USER = "INSERT INTO t_user (USERNAME, PASSWORD) VALUES (?, ?)";
   public void addUser(final User user) throws Exception{
            public void addUser(final User user) throws Exception{
        getJdbcTemplate().update(CREATE_USER,
        new PreparedStatementSetter() {
      public void setValues(PreparedStatement ps)
        throws SQLException {
        ps.setString(1, user.getUserName());
        ps.setString(2, user.getPassword());
      }
     }
    );
  }
}service类中方法。(注意配置时是对add*的方法才自动开启事务的,但是该方法调用后,数据竟然可以save)
public void registerUser(User user) throws Exception{
userDao.addUser(user);
userDao.addUserLog();
}
求高手解答。谢谢。

解决方案 »

  1.   

    换成拦截器实现试试:
    <bean id="transactionInterceptor"
          class="org.springframework.transaction.interceptor.TransactionInterceptor">
          <property name="transactionManager">
           <ref bean="transactionManager" />
          </property>
          <property name="transactionAttributes">
           <props>
            <prop key="delete*">PROPAGATION_REQUIRED</prop>
            <prop key="add*">PROPAGATION_REQUIRED</prop>
            <prop key="update*">PROPAGATION_REQUIRED</prop>
            <prop key="save*">PROPAGATION_REQUIRED</prop>
            <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
           </props>
          </property>
        </bean>
        
         <bean id="autoproxy"
          class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
          <property name="beanNames">
           <list>
            <value>*Service</value>
           </list>
          </property>
          <property name="interceptorNames">
           <list>
               <value>transactionInterceptor</value>
           </list>
          </property>
         </bean>
      

  2.   


    使用拦截器也会提交事务。
    我的本意是把事务设置在service层,并且只有add开头的才开启事务。
    其他不以add开头的service方法,不开启事务,不自动提交。
      

  3.   

    Spring的事务自动管理一般需要四步:
    第一步:配置数据源:实现类和数据库
    第二步:配置事务管理器:实现类和使用的数据源。
    第三步:配置事务拦截器,指定事务拦截的传播属性
    第四步:指定哪些类,包使用什么粒度的拦截。
    --------------------------------------------------------------------------
    Spring的事务配置,有很多种,不过前面两步基本一致,
    第一步:配置数据源:
    例如: <!-- 定义数据源 -->
    <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url"
    value="jdbc:mysql://localhost:3306/db_test7" />
    <property name="username" value="root"/>
    <property name="password" value="better"/>
    </bean>第二步:配置事务管理器:
    例如: <!-- 定义事务管理器 -->
    <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
    </bean>
    下面我将说说Spring几种配置方式第三四步的不同和优缺点:
      

  4.   

    第一种:配置方式(学习用,原理,最基本,实际项目很少用)
    为指定的一个类的特定方法,指定特定的事务方式:
    第三四步合并: <!-- 配置代理定向形式 使用ProxyFactoryBean的子类-->
    <bean id="anoProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>
    <!-- 这里的目标非接口,要导入CGLIB -->
    <property name="target" ref="ano">
    </property>
    <property name="transactionAttributes">
    <props>
    <!-- 如果没有事务则创建一个事务 -->
    <prop key="insert*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>
            <!--这是Headsen自己的类-->
    <bean id="ano" class="com.TransactionTemplate.AnoJdbcTemplate">
    <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>
      

  5.   

    掌握了上面一种方式,就可以使用第二种了:
    第一种要一个类一个的配置,第二种可以一下子指定一组有共同事务需求的类:第三步: <!-- 使用通用配置,试用所有类-->
    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="transactionManager"></property>
    <!-- 定义事务的传播属性 -->
    <property name="transactionAttributes">
    <props>
    <prop key="insert*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>第四步:
    <!-- 定义通用AOP代理 这里也可以使用ProxyFactoryBean,一对一配置-->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames">
    <value>AnoJdbc.*</value>
    <value>这里可以罗列你要事务拦截的类</value>   
    </property>
    <property name="interceptorNames">
    <list>
    <value>transactionInterceptor</value>
    </list>
    </property>
    </bean>CSDN只允许连续回帖三次。
    后面继续,第三种配置方式:
      

  6.   

    最初我是使用第一种方式,但是不起作用。
    然后我使用第2种方式,还是不行。我写了registerUser的方法,数据还是可以insert进数据库。
     <bean id="transactionInterceptor"
          class="org.springframework.transaction.interceptor.TransactionInterceptor">
          <property name="transactionManager">
           <ref bean="transactionManager" />
          </property>
          <property name="transactionAttributes">
           <props>
            <prop key="delete*">PROPAGATION_REQUIRED</prop>
            <prop key="add*">PROPAGATION_REQUIRED</prop>
            <prop key="update*">PROPAGATION_REQUIRED</prop>
            <prop key="save*">PROPAGATION_REQUIRED</prop>
            <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
           </props>
          </property>
        </bean>
        
        <bean id="autoproxy"
          class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
          <property name="beanNames">
           <list>
            <value>*Service</value>
           </list>
          </property>
          <property name="interceptorNames">
           <list>
               <value>transactionInterceptor</value>
           </list>
          </property>
         </bean>
      

  7.   

    第三种方式:这种最常用。灵活简单。使用tx标签。
    第三步:配置事务的处理参数 <!-- 本例使用tx,要加入对应的schema才能自动提示 -->
    <tx:advice id="jdbcTxAdvice"
    transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="add*" propagation="REQUIRED" />
    <tx:method name="del*" propagation="REQUIRED" />
    <tx:method name="get*" propagation="REQUIRED" isolation="DEFAULT" timeout="-1" read-only="true" />
    <tx:method name="find*" propagation="REQUIRED" isolation="DEFAULT" timeout="-1" read-only="true" />
    <tx:method name="*" propagation="REQUIRED"  isolation="DEFAULT" timeout="-1" />
    </tx:attributes>
    </tx:advice>第四步:指定哪些类使用第三步配置的事务 <aop:config proxy-target-class="true">
      <!--DAO包下所有类都进行事务代理-->
    <aop:pointcut id="pointcut1" expression="execution(* com.*.DAO.*.*(..))" />
    <aop:advisor advice-ref="jdbcTxAdvice" pointcut-ref="pointcut1"/>
    <!--你还可以指定额外的处理,-->
    <!--
    <aop:pointcut id="fund" expression="execution(* com.jsjs..*(..))"/>
    <aop:aspect ref="springLog">
    <aop:before pointcut-ref="fund" method="before"/>
    <aop:after-returning pointcut-ref="fund" method="after" returning="retur"/>
    <aop:after-throwing pointcut-ref="fund" method="exception" throwing="ex"/>
    </aop:aspect>
    -->
    </aop:config>
    上面是第三种方式。
    另外看了你问题,老大啊!默认当然是提交的啊!
    即便你不设置事务照样提交啊!你的配置一点问题没有啊。事务的配置起不起作用很难看出来的。
      

  8.   

    我的意图是,在service层控制事务。当进行多张表的操作时可以同时回滚。
    例如:
    public void registerUser(User user) throws Exception{
    userDao.addUser(user);
    userDao.addUserLog();
    }
    先insert到user表,再insert进userLog表,当insert userlog表出错时,回滚事务。
    结果发现采用如下这种方式即使userlog出错,也不会回滚user表。
    <bean id="businessProxy"
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager">
           <ref bean="transactionManager" />
        </property>     <property name="target">
           <ref bean="userService" />
        </property>
        <property name="transactionAttributes">
          <props>
             <prop key="registerUser*">PROPAGATION_REQUIRED</prop>
          </props>
        </property>
      </bean>
    刚刚试了一下发现采用TransactionInterceptor的方式可以实现事务回滚。
    实在不知道前面一种方式为什么不能实现事务回滚。
      

  9.   

    1,数据库必须支持事务(MySql数据库有种引擎是不支持事务的。)
    2,如果是hibernate和jdbc混用,应选择org.springframework.orm.hibernate3.HibernateTransactionManager类处理事务。
    3,不要在有事务的方法中捕获事务定义回滚的异常,否则事务不会回滚。
    4,不要将需要事务的类相互注入。
      

  10.   


    <props>
    <prop key="registerUser*">PROPAGATION_REQUIRED</prop>
    </props><props>
      <!--这个地方不管我怎么配置,当操作数据库时,事务总是被提交 -->
    <prop key="add*">PROPAGATION_REQUIRED</prop>
    </props>
    靠!看了半天 原理粒度问题!怪不得。白白浪费这么多时间。
    add();add();
    两个add两个事务。
      

  11.   


    不是粒度问题,
    <props>
      <!--这个地方的key已经是 registerUser*了,最初的service方法是以add开头的,所以最初的key是add*-->
    <prop key="add*">PROPAGATION_REQUIRED</prop>
    </props>
      

  12.   


    对了事务我配置是在service层,不是在dao层。
    所以 userDao的两个方法不会开启2个事务,只会开启一个事务。如下:
    public void registerUser(User user) throws Exception{
                    //以下2条语句只会开启一个事务。
    userDao.addUser(user);
    userDao.addUserLog();
    }