最近在家里整理书籍,看到一本《Spring in Action》,基于手头上的项目都不是很大,基本上都没有使用Spring,都快忘差不多了,所以写了个Spring与ibatis整合的小例子,权当练手之作,废话少说
DAO类
public interface UserDao { public void addUser(String userName); public void delUser(String userName); public void editUser(String userName); public List getUser(String userName); }
DAOImpl 实现接口类
public class UserImpl extends SqlMapClientDaoSupport implements UserDao{ @Override public void addUser(String userName) { // TODO Auto-generated method stub System.out.println("=======添加用户"+userName); UserModel userModel = new UserModel(); userModel.setLoginName("spring"); userModel.setPasswd("123"); userModel.setUserName(userName); getSqlMapClientTemplate().insert("insertObject",userModel); //第二条测试数据 UserModel userModel2 = new UserModel(); userModel2.setLoginName("spring"); userModel2.setPasswd("123"); userModel2.setUserName(userName+"这是一个测试用户,用来测试spring的事务回滚,如果该数据不能插入进去,那么上面的插入也不会执行成功"); getSqlMapClientTemplate().insert("insertObject",userModel2); } @Override public void delUser(String userName) { // TODO Auto-generated method stub System.out.println("=======删除用户"); } @Override public void editUser(String userName) { // TODO Auto-generated method stub System.out.println("=======编辑用户"); } @Override public List getUser(String userName) { // TODO Auto-generated method stub System.out.println("=======查询用户"); return getSqlMapClientTemplate().queryForList("getAllUser"); } }
注意 public class UserImpl extends SqlMapClientDaoSupport implements UserDao
大家应该在这个类中的addUser方法中可以看到//第二条测试数据 这段代码,其中我在serModel2.setUserName()方法中传了一个很长的用户名参数,这参数的长度已经大于数据库中字段给定的大小,这里就是为了测试事务回滚的。当然,这只是个测试程序,实际应用中,这段代码应该是放到Service层中的
Service层
public class UserServices { //此处因为在spring中注入了userImpl public UserDao userDao; //必须set public void setUserDao(UserDao userDao) { this.userDao = userDao; } /** * 若没有action 则在services里面抛异常,在Dao里面设置事务, * 有action 则在services里面设置事务,在Action抛异常 * 事务和异常不能在一个类里面 */ public void addUser() { try { userDao.addUser("张三"); }catch(RuntimeException e){ System.out.println("出错"); } } public List getUser() { return userDao.getUser("张三"); } }
若没有action 则在services里面抛异常,在Dao里面设置事务, 有action 则在services里面设置事务,在Action抛异常。不然Spring不会实现事务的回滚
userSql.xml ibatis的配置文件,非常简单
<!-- insert one data --> <insert id="insertObject" parameterClass="user"> INSERT INTO sys_user( loginName, userName, passwd) VALUES ( #loginName#, #userName#, #passwd#) </insert>
SqlMapConfig.xml ibatis的配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlMapConfig> <sqlMap resource="user/sql/UserSql.xml"/> </sqlMapConfig>
因为使用了Spring对Ibatis进行管理,所以这里的配置很简单,至于数据库地址的配置这一块,将在下面列出
ServiceFactory 类,这个文件主要是用于测试程序的
package util; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import user.services.UserServices; public class ServiceFactory { private static BeanFactory factory = null; static { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[] {"applicationContext.xml"}); // ApplicationContext context = // new ClassPathXmlApplicationContext("applicationContext.xml"); factory = (BeanFactory) context; } /** * 获得用户服务类 * @return 用户服务 */ public static UserServices getUserInfoDAO(){ return (UserServices) factory.getBean("userServices"); } /** * 获得用户服务类 * @return 用户服务 */ public static UserServices getUserInfoDAO1(){ return (UserServices) factory.getBean("userServices1"); } }
因为applicationContext.xml文件是放在src的根目录下,所以这边只用填写applicationContext.xml即可
applicationContext.xml Spring的配置文件,也是整合的关键地方,这里添加了多个数据库的支持,数据库分别是MySql和SQLite
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:properties/database.properties"/> </bean> <!-- =========================transactionManager========================= --> <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <value>userDao</value> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> <value>transactionInterceptor2</value> </list> </property> </bean> <!-- =================== 配置1 ========================== --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${mysql.driverClassName}"/> <property name="url" value="${mysql.url}"/> <property name="username" value="${mysql.username}"/> <property name="password" value="${mysql.password}"/> </bean> <!-- ================================= 事务处理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED,-SQLException</prop> <prop key="del*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="edit*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <!-- 读取ibatis配置文件 --> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="classpath:SqlMapConfig.xml"/> <property name="dataSource" ref="dataSource"/> </bean> <!-- =================== 配置2 ========================== --> <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${sqlite.driverClassName}"/> <property name="url" value="${sqlite.url}"/> <property name="username" value="${sqlite.username}"/> <property name="password" value="${sqlite.password}"/> </bean> <!-- ================================= 事务处理2 --> <bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource2"/> </bean> <bean id="transactionInterceptor2" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager2"/> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="del*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="edit*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <!-- 读取ibatis配置文件2 --> <bean id="sqlMapClient2" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="classpath:SqlMapConfig.xml" /> <property name="dataSource" ref="dataSource2" /> </bean> <!-- ============ 调用示例 ================ --> <!-- 实现层1 --> <bean id="userDao" class="user.dao.UserImpl"> <property name="sqlMapClient" ref="sqlMapClient" /> </bean> <!-- 服务层的注入1 --> <bean id="userServices" class="user.services.UserServices"> <property name="userDao" ref="userDao" /> </bean> <!-- 实现层2 --> <bean id="userDao1" class="user.dao.UserImpl"> <property name="sqlMapClient" ref="sqlMapClient2"/> </bean> <!-- 服务层的注入2 --> <bean id="userServices1" class="user.services.UserServices"> <property name="userDao" ref="userDao1" /> </bean> </beans>
这里使用了自动事务处理的方法,配置1为MySql的,配置2为SQLite的
整体来说,Spring和ibatis的整合还是很简单的,只要了解了Spring的基本使用,理解了上面的几个需要注意的地方,整合工作就会很简单了,上面的代码中有很多不规范的地方,大家在做整合的过程中一定要严格注意Service层和DAO层的区别,比如说我这里在做对数据库添加用户信息的时候,这一段代码严格意义上来讲,应该放到Service层的。
还有需要说明的是
若没有action 则在services里面抛异常,在Dao里面设置事务, 有action 则在services里面设置事务,在Action抛异常。不然Spring不会实现事务的回滚