spring的事务控制应该说是所有用spring的项目中必不可少的东西。在我所经历过的所有用spring的项目中,IOC和事务控制是必用的。其它的一些东西,根据项目不同会有所选择。为什么要用spring的这两个呢?使用IOC可以让我们的代码进行完全的松耦合。而事务控制,可以让我们基本上在写代码的时候短暂的忘记事务的存在。专心于业务层的实现。下面给出一个spring 事务控制的例子。首页是Action层的代码:

public String createUser() throws Exception ...{
user = new User();
user.setUsername("Gavin");
user.setPassword("123");
user.setUserDetail(new UserDetail());

if (logger.isDebugEnabled()) ...{
logger.debug("创建一个新的用户. " + user.toString());
}

try ...{
userService.saveUser(user);

} catch (Exception e) ...{
if (logger.isDebugEnabled()) ...{
logger.debug("用户操作出错. " + e);
}
}
return Action.SUCCESS;
}Action层只是简单的去调用service层,为了使例子简单,我去掉了一些不必要的东西。只剩下核心的一些。下面给出service层的代码(所有接口用处不大,不给出来)。
package com.websidesoft.service.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.websidesoft.dao.iface.FriendDAO;
import com.websidesoft.dao.iface.UserDAO;
import com.websidesoft.entities.User;
import com.websidesoft.exception.WSSException;
import com.websidesoft.service.iface.UserService;

public class UserServiceManager implements UserService ...{
private static final Log logger = LogFactory.getLog(UserServiceManager.class);
private FriendDAO friendDao;
private UserDAO userDao;


public void deleteUser(int userId) throws WSSException ...{
}

public User getUser(int userId) throws WSSException ...{
return null;
}

public void saveUser(User user) throws WSSException ...{
userDao.saveUser(user);

try ...{
friendDao.saveFriend(user);
} catch (Exception e) ...{
if (logger.isDebugEnabled()) ...{
logger.debug("保存friend出错. " + e);
}
}
// throw new RuntimeException("出错.............");
}

public void updateUser(User user) throws WSSException ...{
}

public FriendDAO getFriendDao() ...{
return friendDao;
}

public void setFriendDao(FriendDAO friendDao) ...{
this.friendDao = friendDao;
}

public UserDAO getUserDao() ...{
return userDao;
}

public void setUserDao(UserDAO userDao) ...{
this.userDao = userDao;
}
}service是重点,给出了所有service层的代码。先给出所有的代码,之后再来详细说明。下面是DAO层代码:
package com.websidesoft.dao.impl;
import java.util.HashMap;
import java.util.Map;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.websidesoft.dao.iface.UserDAO;
import com.websidesoft.entities.User;
import com.websidesoft.exception.DataAccessException;

public class UserDAOImpl extends JdbcDaoSupport implements UserDAO ...{

public void deleteUser(int userId) throws DataAccessException ...{
}

public User getUser(int userId) throws DataAccessException ...{
return null;
}

public void saveUser(User user) throws DataAccessException ...{
String sql = "insert into wss_users(username, password) values (:username, :password)";
NamedParameterJdbcTemplate pstmt = new NamedParameterJdbcTemplate(this.getJdbcTemplate().getDataSource());
Map nameParameters = new HashMap();
nameParameters.put("username", user.getUsername());
nameParameters.put("password", user.getPassword());
pstmt.update(sql, nameParameters);
}

public void updateUser(User user) throws DataAccessException ...{
}
}
package com.websidesoft.dao.impl;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.websidesoft.dao.iface.FriendDAO;
import com.websidesoft.exception.DataAccessException;

public class FriendDAOImpl extends JdbcDaoSupport implements FriendDAO ...{

public void saveFriend(Object o) throws DataAccessException ...{
throw new NullPointerException("不能传入空的参数.");
}
}为了简单和测试,我在FriendDAO中直接抛出异常。下面给出xml配置文件,只是核心的,还有一些bean的ioc就不写出来了。
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/wss"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*"/>
<tx:method name="get*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="userServicePointcut" expression="execution(* com.websidesoft.service.iface.UserService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointcut"/>
<aop:aspect id="userAspect" ref="userLog">
<aop:before pointcut="execution(* com.websidesoft.service.iface.UserService.*(..)) and args(user)" method="saveUser"/>
</aop:aspect>
</aop:config>
<!-- DAO层 -->
<bean id="userDao" class="com.websidesoft.dao.impl.UserDAOImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="friendDao" class="com.websidesoft.dao.impl.FriendDAOImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>上面给出了这个例子的所有代码。下面首先说明一下事务控制的部份。核心的事务控制部份如下:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/wss"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*"/>
<tx:method name="get*"/>
</tx:attributes>
</tx:advice>上面的配置实现了以容器的方式配置数据源。对数据源进行事务管理。看一下service层的代码:

public void saveUser(User user) throws WSSException ...{
userDao.saveUser(user);

try ...{
friendDao.saveFriend(user);
} catch (Exception e) ...{
if (logger.isDebugEnabled()) ...{
logger.debug("保存friend出错. " + e);
}
}
// throw new RuntimeException("出错.............");
}在上面的代码中,如果出现错误,将抛出WSSException异常。这个异常是实现了Exception的全局异常。spring在对事务控制时,只对运行时异常和未检测异常才会进行事务的rollback,也就是说当抛出检测异常将不会被rollback。看上面的例子,我对friendDao.saveFriend(user)进行了try catch动作。因为在friendDao中,我直接抛出抛常。也就是说如果friendDao出错,将不能影响到用户的正常注册。上面的异常不会导致事务回滚。上面的代码运行进,将会用户正常的注册。在下面,我把一行代码注释了,throw new RuntimeException("出错.............");这一代码有什么作用呢?这一句最重要的作用就是,如果打开,那么所有的事务将进行rollback操作。也就是说保存用户将会出错。不会保存成功。
上面只是简单的举了个例子来说明spring2.0中事务控制。当然,还可以控制指定哪些异常将会导致回滚动作。只需要在事务控制的xml中加上rollback-for="异常全名"即可。
本文介绍Spring框架中的事务控制原理及应用实例,通过具体代码展示如何配置数据源,并对service层和DAO层进行事务管理。
166

被折叠的 条评论
为什么被折叠?



