java笔记:自己动手写javaEE框架(五)--Spring

系统 2712 0

上篇文章写到了编程式事务的使用TransactionTemplate类的实现,TransactionTemplate类里的execute方法需要TransactionCallback接口实现类做参数,其接口的定义中只包含一个doInTransaction方法用于执行事务操作,上面的代码中使用匿名类的方式定义TransactionCallback接口实现,并且在doInTransaction()方法中定义事务处理代码。

第五章 声明式事务管理

  我们使用最多的还是Spring声明式事务管理,其实所有Spring事务管理都是基于AOP来实现,而其中的声明式事务才是真正体现AOP全部优点的最佳应用,记得我以前参加面试一说到AOP我就提及声明式事务管理,哎,那个时候对AOP的理解也就仅限于此,太菜了。Spring声明式事务不涉及组件的依赖关系,使用它时候不需要编写任何代码,很大程度的节省了工作量,提高了工作效率。下面我在我的框架里面加入声明式事务,首先修改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:aop
          
          
            ="http://www.springframework.org/schema/aop"
          
          
            
  xmlns:tx
          
          
            ="http://www.springframework.org/schema/tx"
          
          
            
  xsi:schemaLocation
          
          
            ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
          
          
            >
          
          
            <!--
          
          
             扫描该路径下的spring组件 
          
          
            -->
          
          
            <
          
          
            context:component-scan 
          
          
            base-package
          
          
            ="cn.com.sharpxiajun"
          
          
          
          
            />
          
          
            <!--
          
          
             读取资源文件 
          
          
            -->
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="propertyConfigurer"
          
          
             class
          
          
            ="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="locations"
          
          
            >
          
          
            <
          
          
            list
          
          
            >
          
          
            <
          
          
            value
          
          
            >
          
          classpath:conf/constants.properties
          
            </
          
          
            value
          
          
            >
          
          
            </
          
          
            list
          
          
            >
          
          
            </
          
          
            property
          
          
            >
          
          
            </
          
          
            bean
          
          
            >
          
          
            <!--
          
          
             配置数据源 
          
          
            -->
          
          
            <!--
          
          
              <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
             <property name="driverClass" value="${db.driverClass}"/>
             <property name="jdbcUrl" value="${db.jdbcUrl}"/>
             <property name="user" value="${db.user}"/>
             <property name="password" value="${db.password}"/>
         </bean>
          
          
            -->
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="myDataSource"
          
          
             class
          
          
            ="org.apache.commons.dbcp.BasicDataSource"
          
          
             destroy-method
          
          
            ="close"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="driverClassName"
          
          
             value
          
          
            ="${db.driverClass}"
          
          
            />
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="url"
          
          
             value
          
          
            ="${db.jdbcUrl}"
          
          
            />
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="username"
          
          
             value
          
          
            ="${db.user}"
          
          
            />
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="password"
          
          
             value
          
          
            ="${db.password}"
          
          
            />
          
          
            </
          
          
            bean
          
          
            >
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="sqlMapClient"
          
          
             class
          
          
            ="org.springframework.orm.ibatis.SqlMapClientFactoryBean"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="configLocation"
          
          
            >
          
          
            <
          
          
            value
          
          
            >
          
          classpath:conf/SqlMapConfig.xml
          
            </
          
          
            value
          
          
            >
          
          
            </
          
          
            property
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="dataSource"
          
          
             ref
          
          
            ="myDataSource"
          
          
            />
          
          
            </
          
          
            bean
          
          
            >
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="sqlMapClientTemplate"
          
          
             class
          
          
            ="org.springframework.orm.ibatis.SqlMapClientTemplate"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="sqlMapClient"
          
          
            >
          
          
            <
          
          
            ref 
          
          
            local
          
          
            ="sqlMapClient"
          
          
            />
          
          
            </
          
          
            property
          
          
            >
          
          
            </
          
          
            bean
          
          
            >
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="transactionManager"
          
          
             class
          
          
            ="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="dataSource"
          
          
            >
          
          
            <
          
          
            ref 
          
          
            local
          
          
            ="myDataSource"
          
          
            />
          
          
            </
          
          
            property
          
          
            >
          
          
            </
          
          
            bean
          
          
            >
          
          
            <!--
          
          
             声明式事务 
          
          
            -->
          
          
            <
          
          
            tx:advice 
          
          
            id
          
          
            ="txAdvice"
          
          
             transaction-manager
          
          
            ="transactionManager"
          
          
            >
          
          
            <
          
          
            tx:attributes
          
          
            >
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="get*"
          
          
             read-only
          
          
            ="true"
          
          
             propagation
          
          
            ="REQUIRED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="query*"
          
          
             read-only
          
          
            ="true"
          
          
             propagation
          
          
            ="REQUIRED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="find*"
          
          
             read-only
          
          
            ="true"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="list*"
          
          
             read-only
          
          
            ="true"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="search*"
          
          
             read-only
          
          
            ="true"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="add*"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
             isolation
          
          
            ="READ_COMMITTED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="insert*"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
             isolation
          
          
            ="READ_COMMITTED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="del*"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
             isolation
          
          
            ="READ_COMMITTED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="save*"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
             isolation
          
          
            ="READ_COMMITTED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="update*"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
             isolation
          
          
            ="READ_COMMITTED"
          
          
            />
          
          
            <
          
          
            tx:method 
          
          
            name
          
          
            ="modify*"
          
          
              propagation
          
          
            ="REQUIRED"
          
          
             isolation
          
          
            ="READ_COMMITTED"
          
          
            />
          
          
            </
          
          
            tx:attributes
          
          
            >
          
          
            </
          
          
            tx:advice
          
          
            >
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="transactionTemplate"
          
          
             class
          
          
            ="org.springframework.transaction.support.TransactionTemplate"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="transactionManager"
          
          
            >
          
          
            <
          
          
            ref 
          
          
            bean
          
          
            ="transactionManager"
          
          
            />
          
          
            </
          
          
            property
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="propagationBehaviorName"
          
          
            >
          
          
            <
          
          
            value
          
          
            >
          
          PROPAGATION_REQUIRED
          
            </
          
          
            value
          
          
            >
          
          
            </
          
          
            property
          
          
            >
          
          
            </
          
          
            bean
          
          
            >
          
          
            <!--
          
          
             将我自己定义的拦截器生成bean 
          
          
            -->
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="methodServiceAdvisor"
          
          
             class
          
          
            ="cn.com.sharpxiajun.common.aop.MethodServiceAdvisor"
          
          
            />
          
          
            <
          
          
            aop:config
          
          
            >
          
          
            <!--
          
          
            配置规则,满足以下规则的将拦截,第一个*表示所有返回类型,第二个表示service包下的所有class,第三个表示所有方法
          
          
            -->
          
          
            <
          
          
            aop:pointcut 
          
          
            id
          
          
            ="baseServiceMethods"
          
          
             expression
          
          
            ="execution(* cn.com.sharpxiajun.service.*.*(..))"
          
          
            />
          
          
            <!--
          
          
             声明式事务 
          
          
            -->
          
          
            <
          
          
            aop:advisor 
          
          
            advice-ref
          
          
            ="txAdvice"
          
          
             pointcut-ref
          
          
            ="baseServiceMethods"
          
          
          
          
            />
          
          
            <!--
          
          
             符合上面规则的拦截器都会调用到methodServiceAdvisor 
          
          
            -->
          
          
            <
          
          
            aop:advisor 
          
          
            advice-ref
          
          
            ="methodServiceAdvisor"
          
          
             pointcut-ref
          
          
            ="baseServiceMethods"
          
          
            />
          
          
            </
          
          
            aop:config
          
          
            >
          
          
            </
          
          
            beans
          
          
            >
          
        

  这里面添加了<tx:advice id="txAdvice" transaction-manager="transactionManager">,根据方法前缀不同绑定不同的事务策略,然后在<aop:config>里面添加<aop:advisor advice-ref="txAdvice" pointcut-ref="baseServiceMethods" />,那么service包下面类里的方法都会绑定相应的事务管理。在javaEE工程里面到底是DAO层绑定事务还是在Service层绑定事务?这个问题以前有同事问过我,我当时回答是都应该绑定,现在我会说最好只在Service层绑定事务。DAO层在我的理解里应该是数据库操作的映射,那是针对数据的原子操作,而Service层则是把这些各种数据库操作封装成一个业务操作单元,所以Service层的含义更符合事务本质,所以事务最好绑定在Service层。DAO层再绑定事务没必要,而且多余,甚至还会操作不必要的错误。

  接下来我修改USERS.xml映射文件,代码如下:

          
            <?
          
          
            xml version="1.0" encoding="UTF-8"
          
          
            ?>
          
          
            <!
          
          
            DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"
          
          
            >
          
          
            <
          
          
            sqlMap 
          
          
            namespace
          
          
            ="USERS"
          
          
            >
          
          
            <
          
          
            select 
          
          
            id
          
          
            ="queryUserList"
          
          
             parameterClass
          
          
            ="java.util.Map"
          
          
             resultClass
          
          
            ="java.util.HashMap"
          
          
            >
          
          
        select t.username,t.password,t.enabled from users t
    
          
            </
          
          
            select
          
          
            >
          
          
            <!--
          
          
             新增用户信息 
          
          
            -->
          
          
            <
          
          
            insert 
          
          
            id
          
          
            ="addUsers"
          
          
             parameterClass
          
          
            ="java.util.Map"
          
          
            >
          
          
        insert into users
        
          
            <
          
          
            dynamic 
          
          
            prepend
          
          
            ="("
          
          
            >
          
          
            <
          
          
            isNotNull 
          
          
            prepend
          
          
            =","
          
          
             property
          
          
            ="username"
          
          
            >
          
          
                username
            
          
            </
          
          
            isNotNull
          
          
            >
          
          
            <
          
          
            isNotNull 
          
          
            prepend
          
          
            =","
          
          
             property
          
          
            ="password"
          
          
            >
          
          
                password
            
          
            </
          
          
            isNotNull
          
          
            >
          
          
            <
          
          
            isNotNull 
          
          
            prepend
          
          
            =","
          
          
             property
          
          
            ="enabled"
          
          
            >
          
          
                enabled
            
          
            </
          
          
            isNotNull
          
          
            >
          
          
            )        
        
          
            </
          
          
            dynamic
          
          
            >
          
              
        values
        
          
            <
          
          
            dynamic 
          
          
            prepend
          
          
            ="("
          
          
            >
          
          
            <
          
          
            isNotNull 
          
          
            prepend
          
          
            =","
          
          
             property
          
          
            ="username"
          
          
            >
          
          
                #username:VARCHAR#
            
          
            </
          
          
            isNotNull
          
          
            >
          
          
            <
          
          
            isNotNull 
          
          
            prepend
          
          
            =","
          
          
             property
          
          
            ="password"
          
          
            >
          
          
                #password:VARCHAR#
            
          
            </
          
          
            isNotNull
          
          
            >
          
          
            <
          
          
            isNotNull 
          
          
            prepend
          
          
            =","
          
          
             property
          
          
            ="enabled"
          
          
            >
          
          
                #enabled:NUMBER#
            
          
            </
          
          
            isNotNull
          
          
            >
          
          
            )
        
          
            </
          
          
            dynamic
          
          
            >
          
          
            </
          
          
            insert
          
          
            >
          
          
            </
          
          
            sqlMap
          
          
            >
          
        

  修改cn.com.sharpxiajun.dao包下的接口UsersDao,代码如下:

          
            package
          
           cn.com.sharpxiajun.dao;


          
            import
          
           java.util.List;

          
            import
          
           java.util.Map;


          
            public
          
          
            interface
          
           UsersDao {
    
    
          
            public
          
          
            static
          
          
            final
          
           String QUERY_USERS_SQL = "USERS.queryUserList";
    
          
            public
          
          
            static
          
          
            final
          
           String ADD_USERS_SQL = "USERS.addUsers";
    
    
          
            public
          
           List<Map<String, Object>> queryUserList(Map<String, Object> map) 
          
            throws
          
           Exception;
    
    
          
            public
          
           Object addUsers(Map<String, Object> map) 
          
            throws
          
           Exception;

}
        

  修改cn.com.sharpxiajun.dao.impl包下面UsersDaoImpl类,代码如下:

          
            package
          
           cn.com.sharpxiajun.dao.impl;


          
            import
          
           java.util.List;

          
            import
          
           java.util.Map;



          
            import
          
           org.springframework.beans.factory.annotation.Autowired;

          
            import
          
           org.springframework.beans.factory.annotation.Qualifier;

          
            import
          
           org.springframework.context.annotation.Scope;

          
            import
          
           org.springframework.orm.ibatis.SqlMapClientTemplate;

          
            import
          
           org.springframework.stereotype.Repository;


          
            import
          
           cn.com.sharpxiajun.dao.UsersDao;

@SuppressWarnings("unchecked")
@Scope("prototype")
@Repository("usersDao")

          
            public
          
          
            class
          
           UsersDaoImpl 
          
            implements
          
           UsersDao {
    
    @Autowired
    @Qualifier("sqlMapClientTemplate")
    
          
            private
          
           SqlMapClientTemplate sqlMapClientTemplate = 
          
            null
          
          ;

    
          
            public
          
           List<Map<String, Object>> queryUserList(Map<String, Object> map)
            
          
            throws
          
           Exception {
        
          
            return
          
           sqlMapClientTemplate.queryForList(QUERY_USERS_SQL, map);
    }

    @Override
    
          
            public
          
           Object addUsers(Map<String, Object> map) 
          
            throws
          
           Exception {
        
          
            return
          
            sqlMapClientTemplate.insert(ADD_USERS_SQL, map);
    }

}
        

  修改cn.com.sharpxiajun.service包下接口UsersService,代码如下:

          
            package
          
           cn.com.sharpxiajun.service;


          
            import
          
           java.util.List;

          
            import
          
           java.util.Map;


          
            public
          
          
            interface
          
           UsersService {
    
    
          
            public
          
           List<Map<String, Object>> queryUsersList(Map<String, Object> map) 
          
            throws
          
           Exception;
    
    
          
            public
          
           Object addUsers(Map<String, Object> map) 
          
            throws
          
           Exception;

}
        

  修改cn.com.sharpxiajun.service.impl包下类UsersServiceImpl,代码如下:

          
            package
          
           cn.com.sharpxiajun.service.impl;


          
            import
          
           java.util.List;

          
            import
          
           java.util.Map;



          
            import
          
           org.springframework.beans.factory.annotation.Autowired;

          
            import
          
           org.springframework.beans.factory.annotation.Qualifier;

          
            import
          
           org.springframework.context.annotation.Scope;

          
            import
          
           org.springframework.stereotype.Service;


          
            import
          
           cn.com.sharpxiajun.dao.UsersDao;

          
            import
          
           cn.com.sharpxiajun.service.UsersService;

@SuppressWarnings("unchecked")
@Scope("prototype")
@Service("userService")

          
            public
          
          
            class
          
           UsersServiceImpl 
          
            implements
          
           UsersService {
    
    @Autowired
    @Qualifier("usersDao")
    
          
            private
          
           UsersDao usersDao = 
          
            null
          
          ;

    @Override
    
          
            public
          
           List<Map<String, Object>> queryUsersList(Map<String, Object> map)
            
          
            throws
          
           Exception {
        
          
            return
          
           usersDao.queryUserList(map);
    }

    @Override
    
          
            public
          
           Object addUsers(Map<String, Object> map) 
          
            throws
          
           Exception {
        
          
            return
          
           usersDao.addUsers(map);
    }

}
        

  修改cn.com.sharpxiajun.junittest.service包下测试类UsersServiceImplTest,代码如下:

          
            package
          
           cn.com.sharpxiajun.junittest.service;


          
            import
          
           java.util.HashMap;

          
            import
          
           java.util.List;

          
            import
          
           java.util.Map;


          
            import
          
           org.apache.commons.logging.Log;

          
            import
          
           org.apache.commons.logging.LogFactory;

          
            import
          
           org.junit.After;

          
            import
          
           org.junit.Before;

          
            import
          
           org.junit.Test;

          
            import
          
           org.junit.runner.RunWith;

          
            import
          
           org.springframework.beans.factory.annotation.Autowired;

          
            import
          
           org.springframework.test.context.ContextConfiguration;

          
            import
          
           org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;

          
            import
          
           org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

          
            import
          
           org.springframework.test.context.transaction.TransactionConfiguration;


          
            import
          
           cn.com.sharpxiajun.service.UsersService;

          
            import
          
           cn.com.sharpxiajun.service.impl.UsersServiceImpl;

@RunWith(SpringJUnit4ClassRunner.
          
            class
          
          )
@ContextConfiguration(locations={"classpath:conf/applicationContext.xml"})
@TransactionConfiguration(defaultRollback = 
          
            false
          
          )

          
            public
          
          
            class
          
           UsersServiceImplTest 
          
            extends
          
          
        AbstractTransactionalJUnit4SpringContextTests {
    
    
          
            private
          
          
            final
          
          
            static
          
           Log log = LogFactory.getLog(UsersServiceImpl.
          
            class
          
          );
    
    @Autowired
    
          
            private
          
           UsersService usersService = 
          
            null
          
          ;
    
    
          
            public
          
           UsersServiceImplTest()
    {
        System.out.println("初始化测试类....");
    }
    
    @Before
    
          
            public
          
          
            void
          
           setUp() 
          
            throws
          
           Exception
    {
        System.out.println("测试开始....");
    }
    
    @After
    
          
            public
          
          
            void
          
           tearDown() 
          
            throws
          
           Exception
    {
        System.out.println("测试结束!!");
    }
    
    @Test
    
          
            public
          
          
            void
          
           testQueryUserList()
    {
        Map<String, Object> map = 
          
            new
          
           HashMap<String, Object>();
        map.put("username", "sharpxiajun");
        
          
            try
          
           {
            List<Map<String, Object>> list = usersService.queryUsersList(map);
            log.info(list);
        } 
          
            catch
          
           (Exception e) {
            e.printStackTrace();
        }
    }
    
    @Test
    
          
            public
          
          
            void
          
           testAddUsers()
    {
        Map<String, Object> map = 
          
            new
          
           HashMap<String, Object>();
        map.put("username", "xiajun");
        map.put("password", "xiajun");
        map.put("enabled", 1);
        
        
          
            try
          
           {
            Object obj = usersService.addUsers(map);
            log.info("testAddUsers:" + obj);
        } 
          
            catch
          
           (Exception e) {
            e.printStackTrace();
        }
    }

}
        

  运行测试类,结果如下:

java笔记:自己动手写javaEE框架(五)--Spring事务管理学习

  数据新增了,但是没有体现事务的作用,我前面写事务示例代码也没有考虑到如何表现事务的作用,为了体现事务作用,我在USERS.xml配置文件里添加新方法,代码如下:

          
            <!--
          
          
             修改用户信息 
          
          
            -->
          
          
            <
          
          
            update 
          
          
            id
          
          
            ="updateUsers"
          
          
             parameterClass
          
          
            ="java.util.Map"
          
          
            >
          
          
        update users set errinfo = 'error'
    
          
            </
          
          
            update
          
          
            >
          
        

  修改cn.com.sharpxiajun.dao包下的UsersDao接口,代码如下:

          
            package
          
           cn.com.sharpxiajun.dao;


          
            import
          
           java.util.List;

          
            import
          
           java.util.Map;


          
            public
          
          
            interface
          
           UsersDao {
    
    
          
            public
          
          
            static
          
          
            final
          
           String QUERY_USERS_SQL = "USERS.queryUserList";
    
          
            public
          
          
            static
          
          
            final
          
           String ADD_USERS_SQL = "USERS.addUsers";
    
          
            public
          
          
            static
          
          
            final
          
           String UPDATE_USERS_SQL = "USERS.updateUsers";
    
    
          
            public
          
           List<Map<String, Object>> queryUserList(Map<String, Object> map) 
          
            throws
          
           Exception;
    
    
          
            public
          
           Object addUsers(Map<String, Object> map) 
          
            throws
          
           Exception;
    
    
          
            public
          
           Object updateUsers(Map<String, Object> map) 
          
            throws
          
           Exception;

}
        

  修改cn.com.sharpxiajun.dao.impl包下的UsersDaoImpl类,代码如下:

          
            package
          
           cn.com.sharpxiajun.dao.impl;


          
            import
          
           java.util.List;

          
            import
          
           java.util.Map;



          
            import
          
           org.springframework.beans.factory.annotation.Autowired;

          
            import
          
           org.springframework.beans.factory.annotation.Qualifier;

          
            import
          
           org.springframework.context.annotation.Scope;

          
            import
          
           org.springframework.orm.ibatis.SqlMapClientTemplate;

          
            import
          
           org.springframework.stereotype.Repository;


          
            import
          
           cn.com.sharpxiajun.dao.UsersDao;

@SuppressWarnings("unchecked")
@Scope("prototype")
@Repository("usersDao")

          
            public
          
          
            class
          
           UsersDaoImpl 
          
            implements
          
           UsersDao {
    
    @Autowired
    @Qualifier("sqlMapClientTemplate")
    
          
            private
          
           SqlMapClientTemplate sqlMapClientTemplate = 
          
            null
          
          ;

    
          
            public
          
           List<Map<String, Object>> queryUserList(Map<String, Object> map)
            
          
            throws
          
           Exception {
        
          
            return
          
           sqlMapClientTemplate.queryForList(QUERY_USERS_SQL, map);
    }

    @Override
    
          
            public
          
           Object addUsers(Map<String, Object> map) 
          
            throws
          
           Exception {
        
          
            return
          
            sqlMapClientTemplate.insert(ADD_USERS_SQL, map);
    }

    @Override
    
          
            public
          
           Object updateUsers(Map<String, Object> map) 
          
            throws
          
           Exception {
        
          
            return
          
           sqlMapClientTemplate.update(UPDATE_USERS_SQL, map);
    }

}
        

  在cn.com.sharpxiajun.service包的UsersService接口里添加方法:

          
            public
          
          
            void
          
           updateUsers(Map<String, Object> map) 
          
            throws
          
           Exception;
        

  在cn.com.sharpxiajun.service.impl下的UsersServiceImpl类里实现该方法,代码如下:

              @Override
    
          
            public
          
          
            void
          
           updateUsers(Map<String, Object> map) 
          
            throws
          
           Exception {
        usersDao.addUsers(map);
        usersDao.updateUsers(map);
    }
        

  从上面代码可以看出USERS.xml的update方法是不能被执行,程序一定会报出异常,如果方法绑定了事务,那么usersDao.addUsers(map);操作会被回滚掉,也就是新增操作不会成功,下面我在cn.com.sharpxiajun.junittest.service包下的UsersServiceImplTest类里添加新的测试方法,代码如下:

              @Test
    
          
            public
          
          
            void
          
           testUpdateUsers()
    {
        Map<String, Object> map = 
          
            new
          
           HashMap<String, Object>();
        map.put("username", "sharp");
        map.put("password", "sharp");
        map.put("enabled", 1);
        
        
          
            try
          
           {
            usersService.updateUsers(map);
        } 
          
            catch
          
           (Exception e) {
            e.printStackTrace();
        }
    }
        

(注意:最好把测试新增方法的代码注释掉)

  运行测试类,控制台会打印出下面异常:

          2011-10-25 23:10:59  SQLErrorCodesFactory - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
org.springframework.jdbc.BadSqlGrammarException: SqlMapClient operation; bad SQL grammar []; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred in cn/com/sharpxiajun/dao/sqlmap/USERS.xml.  
--- The error occurred 
          
            while
          
           applying a parameter map.  
--- Check the USERS.updateUsers-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'errinfo' in 'field list'
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:233)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:203)
    at org.springframework.orm.ibatis.SqlMapClientTemplate.update(SqlMapClientTemplate.java:378)
    at cn.com.sharpxiajun.dao.impl.UsersDaoImpl.updateUsers(UsersDaoImpl.java:36)
    at cn.com.sharpxiajun.service.impl.UsersServiceImpl.updateUsers(UsersServiceImpl.java:45)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at cn.com.sharpxiajun.common.aop.MethodServiceAdvisor.invoke(MethodServiceAdvisor.java:31)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy18.updateUsers(Unknown Source)
    at cn.com.sharpxiajun.junittest.service.UsersServiceImplTest.testUpdateUsers(UsersServiceImplTest.java:103)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred in cn/com/sharpxiajun/dao/sqlmap/USERS.xml.  
--- The error occurred 
          
            while
          
           applying a parameter map.  
--- Check the USERS.updateUsers-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'errinfo' in 'field list'
    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeUpdate(MappedStatement.java:107)
    at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.update(SqlMapExecutorDelegate.java:457)
    at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.update(SqlMapSessionImpl.java:90)
    at org.springframework.orm.ibatis.SqlMapClientTemplate$9.doInSqlMapClient(SqlMapClientTemplate.java:380)
    at org.springframework.orm.ibatis.SqlMapClientTemplate$9.doInSqlMapClient(SqlMapClientTemplate.java:1)
    at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:200)
    ... 49 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'errinfo' in 'field list'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at com.mysql.jdbc.Util.getInstance(Util.java:381)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1031)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:957)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3376)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3308)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1837)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1961)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2543)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1737)
    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:998)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:169)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.ibatis.common.jdbc.logging.PreparedStatementLogProxy.invoke(PreparedStatementLogProxy.java:62)
    at $Proxy21.execute(Unknown Source)
    at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate(SqlExecutor.java:80)
    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.sqlExecuteUpdate(MappedStatement.java:216)
    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeUpdate(MappedStatement.java:94)
    ... 54 more
测试结束!!
2011-10-25 23:10:59  TestContextManager - Caught exception 
          
            while
          
           allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@6798eb] to process 'after' execution 
          
            for
          
           test: method [
          
            public
          
          
            void
          
           cn.com.sharpxiajun.junittest.service.UsersServiceImplTest.testUpdateUsers()], instance [cn.com.sharpxiajun.junittest.service.UsersServiceImplTest@168989e], exception [
          
            null
          
          ]
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:717)
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.endTransaction(TransactionalTestExecutionListener.java:516)
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener.endTransaction(TransactionalTestExecutionListener.java:291)
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:184)
    at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:406)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:90)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
        

  结果如下:

java笔记:自己动手写javaEE框架(五)--Spring事务管理学习

  没有新的记录被添加,事务被成功绑定了~~~。

  那么如果我们写在Service里面的方法没有用applicationContext.xml里面设置的前缀,效果会如何了?

  我在cn.com.sharpxiajun.service包的UsersService接口下添加新方法,代码如下:

          
            public
          
          
            void
          
           noTransactionMethod(Map<String, Object> map) 
          
            throws
          
           Exception;
        

  在cn.com.sharpxiajun.service.impl包里UsersServiceImpl类实现该方法,代码如下:

              @Override
    
          
            public
          
          
            void
          
           noTransactionMethod(Map<String, Object> map) 
          
            throws
          
           Exception {
        usersDao.addUsers(map);
        usersDao.updateUsers(map);
        
    }
        

  最后在cn.com.sharpxiajun.junittest.service包下,修改UsersServiceImplTest测试类,代码如下:

          
            //
          
          
                @Test

          
          
            //
          
          
                public void testAddUsers()

          
          
            //
          
          
                {

          
          
            //
          
          
                    Map<String, Object> map = new HashMap<String, Object>();

          
          
            //
          
          
                    map.put("username", "xiajun");

          
          
            //
          
          
                    map.put("password", "xiajun");

          
          
            //
          
          
                    map.put("enabled", 1);

          
          
            //
          
          
          
          
            //
          
          
                    try {

          
          
            //
          
          
                        Object obj = usersService.addUsers(map);

          
          
            //
          
          
                        log.info("testAddUsers:" + obj);

          
          
            //
          
          
                    } catch (Exception e) {

          
          
            //
          
          
                        e.printStackTrace();

          
          
            //
          
          
                    }

          
          
            //
          
          
                }
          
          
          
          
    @Test
    
          
            public
          
          
            void
          
           testNoTransactionMethod()
    {
        Map<String, Object> map = 
          
            new
          
           HashMap<String, Object>();
        map.put("username", "sharp");
        map.put("password", "sharp");
        map.put("enabled", 1);
        
        
          
            try
          
           {
            usersService.noTransactionMethod(map);
        } 
          
            catch
          
           (Exception e) {
            e.printStackTrace();
        }
    }
    

          
            //
          
          
                @Test

          
          
            //
          
          
                public void testUpdateUsers()

          
          
            //
          
          
                {

          
          
            //
          
          
                    Map<String, Object> map = new HashMap<String, Object>();

          
          
            //
          
          
                    map.put("username", "sharp");

          
          
            //
          
          
                    map.put("password", "sharp");

          
          
            //
          
          
                    map.put("enabled", 1);

          
          
            //
          
          
          
          
            //
          
          
                    try {

          
          
            //
          
          
                        usersService.updateUsers(map);

          
          
            //
          
          
                    } catch (Exception e) {

          
          
            //
          
          
                        e.printStackTrace();

          
          
            //
          
          
                    }

          
          
            //
          
          
                }
          
        

  运行测试类,控制台打印出的异常是:

          
            2011
          
          -
          
            10
          
          -
          
            25
          
          
            23
          
          :
          
            28
          
          :
          
            00
          
            SQLErrorCodesFactory - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
org.springframework.jdbc.BadSqlGrammarException: SqlMapClient operation; bad SQL grammar []; nested exception 
          
            is
          
           com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred 
          
            in
          
           cn/com/sharpxiajun/dao/sqlmap/USERS.xml.  
--- The error occurred 
          
            while
          
           applying a parameter map.  
--- Check the USERS.updateUsers-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 
          
            '
          
          
            errinfo
          
          
            '
          
          
            in
          
          
            '
          
          
            field list
          
          
            '
          
          
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:
          
            233
          
          )
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:
          
            72
          
          )
    at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:
          
            203
          
          )
    at org.springframework.orm.ibatis.SqlMapClientTemplate.update(SqlMapClientTemplate.java:
          
            378
          
          )
    at cn.com.sharpxiajun.dao.impl.UsersDaoImpl.updateUsers(UsersDaoImpl.java:
          
            36
          
          )
    at cn.com.sharpxiajun.service.impl.UsersServiceImpl.noTransactionMethod(UsersServiceImpl.java:
          
            38
          
          )
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
          
            39
          
          )
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
          
            25
          
          )
    at java.lang.reflect.Method.invoke(Method.java:
          
            597
          
          )
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:
          
            309
          
          )
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:
          
            183
          
          )
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:
          
            150
          
          )
    at cn.com.sharpxiajun.common.aop.MethodServiceAdvisor.invoke(MethodServiceAdvisor.java:
          
            31
          
          )
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:
          
            172
          
          )
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:
          
            110
          
          )
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:
          
            172
          
          )
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:
          
            89
          
          )
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:
          
            172
          
          )
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:
          
            202
          
          )
    at $Proxy18.noTransactionMethod(Unknown Source)
    at cn.com.sharpxiajun.junittest.service.UsersServiceImplTest.testNoTransactionMethod(UsersServiceImplTest.java:
          
            88
          
          )
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
          
            39
          
          )
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
          
            25
          
          )
    at java.lang.reflect.Method.invoke(Method.java:
          
            597
          
          )
    at org.junit.runners.model.FrameworkMethod$
          
            1
          
          .runReflectiveCall(FrameworkMethod.java:
          
            44
          
          )
    at org.junit.
          
            internal
          
          .runners.model.ReflectiveCallable.run(ReflectiveCallable.java:
          
            15
          
          )
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:
          
            41
          
          )
    at org.junit.
          
            internal
          
          .runners.statements.InvokeMethod.evaluate(InvokeMethod.java:
          
            20
          
          )
    at org.junit.
          
            internal
          
          .runners.statements.RunBefores.evaluate(RunBefores.java:
          
            28
          
          )
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:
          
            74
          
          )
    at org.junit.
          
            internal
          
          .runners.statements.RunAfters.evaluate(RunAfters.java:
          
            31
          
          )
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:
          
            82
          
          )
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:
          
            72
          
          )
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:
          
            240
          
          )
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:
          
            50
          
          )
    at org.junit.runners.ParentRunner$
          
            3
          
          .run(ParentRunner.java:
          
            193
          
          )
    at org.junit.runners.ParentRunner$
          
            1
          
          .schedule(ParentRunner.java:
          
            52
          
          )
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:
          
            191
          
          )
    at org.junit.runners.ParentRunner.access$
          
            000
          
          (ParentRunner.java:
          
            42
          
          )
    at org.junit.runners.ParentRunner$
          
            2
          
          .evaluate(ParentRunner.java:
          
            184
          
          )
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:
          
            61
          
          )
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:
          
            70
          
          )
    at org.junit.runners.ParentRunner.run(ParentRunner.java:
          
            236
          
          )
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:
          
            180
          
          )
    at org.eclipse.jdt.
          
            internal
          
          .junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:
          
            49
          
          )
    at org.eclipse.jdt.
          
            internal
          
          .junit.runner.TestExecution.run(TestExecution.java:
          
            38
          
          )
    at org.eclipse.jdt.
          
            internal
          
          .junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
          
            467
          
          )
    at org.eclipse.jdt.
          
            internal
          
          .junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
          
            683
          
          )
    at org.eclipse.jdt.
          
            internal
          
          .junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:
          
            390
          
          )
    at org.eclipse.jdt.
          
            internal
          
          .junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:
          
            197
          
          )
Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred 
          
            in
          
           cn/com/sharpxiajun/dao/sqlmap/USERS.xml.  
--- The error occurred 
          
            while
          
           applying a parameter map.  
--- Check the USERS.updateUsers-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 
          
            '
          
          
            errinfo
          
          
            '
          
          
            in
          
          
            '
          
          
            field list
          
          
            '
          
          
    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeUpdate(MappedStatement.java:
          
            107
          
          )
    at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.update(SqlMapExecutorDelegate.java:
          
            457
          
          )
    at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.update(SqlMapSessionImpl.java:
          
            90
          
          )
    at org.springframework.orm.ibatis.SqlMapClientTemplate$
          
            9
          
          .doInSqlMapClient(SqlMapClientTemplate.java:
          
            380
          
          )
    at org.springframework.orm.ibatis.SqlMapClientTemplate$
          
            9
          
          .doInSqlMapClient(SqlMapClientTemplate.java:
          
            1
          
          )
    at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:
          
            200
          
          )
    ... 
          
            49
          
           more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 
          
            '
          
          
            errinfo
          
          
            '
          
          
            in
          
          
            '
          
          
            field list
          
          
            '
          
          
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:
          
            39
          
          )
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:
          
            27
          
          )
    at java.lang.reflect.Constructor.newInstance(Constructor.java:
          
            513
          
          )
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:
          
            406
          
          )
    at com.mysql.jdbc.Util.getInstance(Util.java:
          
            381
          
          )
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:
          
            1031
          
          )
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:
          
            957
          
          )
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:
          
            3376
          
          )
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:
          
            3308
          
          )
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:
          
            1837
          
          )
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:
          
            1961
          
          )
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:
          
            2543
          
          )
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:
          
            1737
          
          )
    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:
          
            998
          
          )
    at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:
          
            169
          
          )
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
          
            39
          
          )
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
          
            25
          
          )
    at java.lang.reflect.Method.invoke(Method.java:
          
            597
          
          )
    at com.ibatis.common.jdbc.logging.PreparedStatementLogProxy.invoke(PreparedStatementLogProxy.java:
          
            62
          
          )
    at $Proxy21.execute(Unknown Source)
    at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate(SqlExecutor.java:
          
            80
          
          )
    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.sqlExecuteUpdate(MappedStatement.java:
          
            216
          
          )
    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeUpdate(MappedStatement.java:
          
            94
          
          )
    ... 
          
            54
          
           more
        

  我们发现这里面少了事务回滚的异常,数据库查询结果如下:

java笔记:自己动手写javaEE框架(五)--Spring事务管理学习

  有记录被新增了~~~

第六章 通过注解绑定事务管理

  声明式事务咋看一下还是十分简单的,但是Spring引入注解后还有更加简单的配置,请看修改后新的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:aop
          
          
            ="http://www.springframework.org/schema/aop"
          
          
            
  xmlns:tx
          
          
            ="http://www.springframework.org/schema/tx"
          
          
            
  xsi:schemaLocation
          
          
            ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
          
          
            >
          
          
            <!--
          
          
             扫描该路径下的spring组件 
          
          
            -->
          
          
            <
          
          
            context:component-scan 
          
          
            base-package
          
          
            ="cn.com.sharpxiajun"
          
          
          
          
            />
          
          
            <!--
          
          
             读取资源文件 
          
          
            -->
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="propertyConfigurer"
          
          
             class
          
          
            ="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="locations"
          
          
            >
          
          
            <
          
          
            list
          
          
            >
          
          
            <
          
          
            value
          
          
            >
          
          classpath:conf/constants.properties
          
            </
          
          
            value
          
          
            >
          
          
            </
          
          
            list
          
          
            >
          
          
            </
          
          
            property
          
          
            >
          
          
            </
          
          
            bean
          
          
            >
          
          
            <!--
          
          
             配置数据源 
          
          
            -->
          
          
            <!--
          
          
              <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
             <property name="driverClass" value="${db.driverClass}"/>
             <property name="jdbcUrl" value="${db.jdbcUrl}"/>
             <property name="user" value="${db.user}"/>
             <property name="password" value="${db.password}"/>
         </bean>
          
          
            -->
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="myDataSource"
          
          
             class
          
          
            ="org.apache.commons.dbcp.BasicDataSource"
          
          
             destroy-method
          
          
            ="close"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="driverClassName"
          
          
             value
          
          
            ="${db.driverClass}"
          
          
            />
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="url"
          
          
             value
          
          
            ="${db.jdbcUrl}"
          
          
            />
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="username"
          
          
             value
          
          
            ="${db.user}"
          
          
            />
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="password"
          
          
             value
          
          
            ="${db.password}"
          
          
            />
          
          
            </
          
          
            bean
          
          
            >
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="sqlMapClient"
          
          
             class
          
          
            ="org.springframework.orm.ibatis.SqlMapClientFactoryBean"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="configLocation"
          
          
            >
          
          
            <
          
          
            value
          
          
            >
          
          classpath:conf/SqlMapConfig.xml
          
            </
          
          
            value
          
          
            >
          
          
            </
          
          
            property
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="dataSource"
          
          
             ref
          
          
            ="myDataSource"
          
          
            />
          
          
            </
          
          
            bean
          
          
            >
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="sqlMapClientTemplate"
          
          
             class
          
          
            ="org.springframework.orm.ibatis.SqlMapClientTemplate"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="sqlMapClient"
          
          
            >
          
          
            <
          
          
            ref 
          
          
            local
          
          
            ="sqlMapClient"
          
          
            />
          
          
            </
          
          
            property
          
          
            >
          
          
            </
          
          
            bean
          
          
            >
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="transactionManager"
          
          
             class
          
          
            ="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="dataSource"
          
          
            >
          
          
            <
          
          
            ref 
          
          
            local
          
          
            ="myDataSource"
          
          
            />
          
          
            </
          
          
            property
          
          
            >
          
          
            </
          
          
            bean
          
          
            >
          
          
            <!--
          
          
             声明式事务 
          
          
            -->
          
          
            <!--
          
          
              <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="get*" read-only="true" propagation="REQUIRED"/>
                <tx:method name="query*" read-only="true" propagation="REQUIRED"/>
                <tx:method name="find*" read-only="true"  propagation="REQUIRED"/>
                <tx:method name="list*" read-only="true"  propagation="REQUIRED"/>
                <tx:method name="search*" read-only="true"  propagation="REQUIRED"/>
                <tx:method name="add*"  propagation="REQUIRED" isolation="READ_COMMITTED"/>
                <tx:method name="insert*"  propagation="REQUIRED" isolation="READ_COMMITTED"/>
                <tx:method name="del*"  propagation="REQUIRED" isolation="READ_COMMITTED"/>
                <tx:method name="save*"  propagation="REQUIRED" isolation="READ_COMMITTED"/>
                <tx:method name="update*"  propagation="REQUIRED" isolation="READ_COMMITTED"/>
                <tx:method name="modify*"  propagation="REQUIRED" isolation="READ_COMMITTED"/>
            </tx:attributes>
        </tx:advice>
          
          
            -->
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="transactionTemplate"
          
          
             class
          
          
            ="org.springframework.transaction.support.TransactionTemplate"
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="transactionManager"
          
          
            >
          
          
            <
          
          
            ref 
          
          
            bean
          
          
            ="transactionManager"
          
          
            />
          
          
            </
          
          
            property
          
          
            >
          
          
            <
          
          
            property 
          
          
            name
          
          
            ="propagationBehaviorName"
          
          
            >
          
          
            <
          
          
            value
          
          
            >
          
          PROPAGATION_REQUIRED
          
            </
          
          
            value
          
          
            >
          
          
            </
          
          
            property
          
          
            >
          
          
            </
          
          
            bean
          
          
            >
          
          
            <!--
          
          
             将我自己定义的拦截器生成bean 
          
          
            -->
          
          
            <
          
          
            bean 
          
          
            id
          
          
            ="methodServiceAdvisor"
          
          
             class
          
          
            ="cn.com.sharpxiajun.common.aop.MethodServiceAdvisor"
          
          
            />
          
          
            <
          
          
            aop:config
          
          
            >
          
          
            <!--
          
          
            配置规则,满足以下规则的将拦截,第一个*表示所有返回类型,第二个表示service包下的所有class,第三个表示所有方法
          
          
            -->
          
          
            <
          
          
            aop:pointcut 
          
          
            id
          
          
            ="baseServiceMethods"
          
          
             expression
          
          
            ="execution(* cn.com.sharpxiajun.service.*.*(..))"
          
          
            />
          
          
            <!--
          
          
             声明式事务 
          
          
            -->
          
          
            <!--
          
          
              <aop:advisor advice-ref="txAdvice" pointcut-ref="baseServiceMethods" />
          
          
            -->
          
          
            <!--
          
          
             符合上面规则的拦截器都会调用到methodServiceAdvisor 
          
          
            -->
          
          
            <
          
          
            aop:advisor 
          
          
            advice-ref
          
          
            ="methodServiceAdvisor"
          
          
             pointcut-ref
          
          
            ="baseServiceMethods"
          
          
            />
          
          
            </
          
          
            aop:config
          
          
            >
          
          
            <
          
          
            tx:annotation-driven 
          
          
            transaction-manager
          
          
            ="transactionManager"
          
          
            />
          
          
            </
          
          
            beans
          
          
            >
          
        

  配置文件里我把原来的声明式配置内容注释掉了,然后加入了<tx:annotation-driven transaction-manager="transactionManager"/>。

  然后在cn.com.sharpxiajun.service.impl包下的UsersServiceImpl类加入@Transactional注解,代码如下:

          @SuppressWarnings("unchecked")
@Scope("prototype")
@Transactional
@Service("userService")

          
            public
          
          
            class
          
           UsersServiceImpl 
          
            implements
          
           UsersService {
......................................................
        

  将数据库里的数据都清除掉,运行测试类UsersServiceImplTest,测试service下的noTransactionMethod方法和updateUsers方法,结果显示数据都没有新增成功,这就说明事务绑定是成功了,这个简单吧。

  总结下了:事务很重要,我希望我这两篇博客能给童鞋们一点帮助。

  下一篇文章将把struts2框架引入到我写的框架。

java笔记:自己动手写javaEE框架(五)--Spring事务管理学习


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论