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

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

第五章 声明式事务管理

我们使用最多的还是Spring声明式事务管理,其实所有Spring事务管理都是基于AOP来实现,而其中的声明式事务才是真正体现AOP全部优点的最佳应用,记得我以前参加面试一说到AOP我就提及声明式事务管理,哎,那个时候对AOP的理解也就仅限于此,太菜了。Spring声明式事务不涉及组件的依赖关系,使用它时候不需要编写任何代码,很大程度的节省了工作量,提高了工作效率。下面我在我的框架里面加入声明式事务,首先修改applicationContext.xml配置文件,代码如下:

classpath:conf/constants.properties

classpath:conf/SqlMapConfig.xml

PROPAGATION_REQUIRED

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

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

select t.username,t.password,t.enabled from users t

insert into users

username

password

enabled

)

values

#username:VARCHAR#

#password:VARCHAR#

#enabled:NUMBER#

)

修改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> queryUserList(Map map) throws Exception;

public Object addUsers(Map 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> queryUserList(Map map)

throws Exception {

return sqlMapClientTemplate.queryForList(QUERY_USERS_SQL, map);

}

@Override

public Object addUsers(Map 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> queryUsersList(Map map) throws Exception;

public Object addUsers(Map 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> queryUsersList(Map map)

throws Exception {

return usersDao.queryUserList(map);

}

@Override

public Object addUsers(Map 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 map = new HashMap();

map.put("username", "sharpxiajun");

try {

List> list = usersService.queryUsersList(map);

log.info(list);

} catch (Exception e) {

e.printStackTrace();

}

}

@Test

public void testAddUsers()

{

Map map = new HashMap();

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();

}

}

}

运行测试类,结果如下:

d49ac61719935ce55e266cf10aadda3a.png

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

update users set errinfo = 'error'

修改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> queryUserList(Map map) throws Exception;

public Object addUsers(Map map) throws Exception;

public Object updateUsers(Map 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> queryUserList(Map map)

throws Exception {

return sqlMapClientTemplate.queryForList(QUERY_USERS_SQL, map);

}

@Override

public Object addUsers(Map map) throws Exception {

return sqlMapClientTemplate.insert(ADD_USERS_SQL, map);

}

@Override

public Object updateUsers(Map map) throws Exception {

return sqlMapClientTemplate.update(UPDATE_USERS_SQL, map);

}

}

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

public void updateUsers(Map map) throws Exception;

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

@Override

public void updateUsers(Map 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 map = new HashMap();

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)

结果如下:

4bc887b2fc62649c637fb2c22affe0ac.png

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

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

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

public void noTransactionMethod(Map map) throws Exception;

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

@Override

public void noTransactionMethod(Map map) throws Exception {

usersDao.addUsers(map);

usersDao.updateUsers(map);

}

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

//@Test//public void testAddUsers()//{//Map map = new HashMap();//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 map = new HashMap();

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 map = new HashMap();//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

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

b59a624067188cb1d11c0a9dea73410a.png

有记录被新增了~~~

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

声明式事务咋看一下还是十分简单的,但是Spring引入注解后还有更加简单的配置,请看修改后新的applicationContext.xml配置文件:

classpath:conf/constants.properties

classpath:conf/SqlMapConfig.xml

PROPAGATION_REQUIRED

配置文件里我把原来的声明式配置内容注释掉了,然后加入了。

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

@SuppressWarnings("unchecked")

@Scope("prototype")

@Transactional

@Service("userService")

public class UsersServiceImpl implements UsersService {

......................................................

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值