基于Spring+Ibatis的安全线程实现
过去做过一些基于spring、hibernate整合应用的实例,本人感觉spring与hibernate最好的结合就是泛型Dao的实现,代码量节省了一半,而且业务逻辑一目了然。
后来做别的系统时候考虑过这样的框架,但是数据库结构如果不固定,动态生成的东西比较多这个时候只好放弃了hibernate而选择了同样具有orm性能的ibatis,下面就spring与ibatis的结合相关配置做下说明(如有不同意见,希望交流)
首先spring和ibatis具体下载和安装就不多说了。直接切入正题
Spring框架下的ibatis应用,特别是在容器事务管理模式下的ibatis应用开发
部署如下:
首先spring配置文件:
Spring_base.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans default-lazy-init="true"> <!-- 配置数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName"> <value>net.sourceforge.jtds.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:jtds:sqlserver://localhost:1433/test</value> </property> <property name="username"> <value>sa</value> </property> <property name="password"> <value>sa</value> </property> <property name="maxActive"> <value>10</value> </property> <property name="maxIdle"> <value>2</value> </property> <property name="maxWait"> <value>300</value> </property> </bean> /////////////////// dataSource:配置你的数据源连接 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"> <value>SqlMap_config.xml</value> </property> <property name="dataSource"><!-- 从指定dataSource中获取数据源 亦可把该定义放到每个自定义Dao中--> <ref bean="dataSource" /> </property> </bean> //////////////////// sqlMapClient:集成ibatis配置文件和把数据源与ibatis相关联 <!-- 配置事务管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref local="dataSource" /> </property> </bean> ///////////////// transactionManager:配置事务管理 <!--公共组件--> <import resource="spring_other.xml" /> ////////////把用户自定义Bean与基本bean分开,集成进去spring_other.xml文件 </beans>
以上是spring 把一些ibatis相关配置集成到自己的配置文件里面
Spring_other.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="userService" class="com.user.UserServiceImpl"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <property name="userDao"> <ref local="userDao" /> </property> </bean> ////////////////////////使用service管理所有用户自定义bean和Dao操作,用来设置事务回滚,线程安全等。 <bean id="userDao" class="com.user.dao.UserDaoImpl"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> ///////////////用户自定义Dao操作,因spring_base.xml中sqlMapClient已经把dataSource包含,故dataSource不再声明,如果该操作需要别的数据连接,可加入例如: ////////<property name=”dataSource1” ref=”dataSource1”/>////////// </beans>
Spring_other.xml存放用户自定义bean
SqlMap_config.xml
<?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> <settings lazyLoadingEnabled="true" useStatementNamespaces="true" enhancementEnabled="true" errorTracingEnabled="true" /> /////////////定义ibatis相关操作参数,例如延迟加载,命名空间是否生效,是否打开缓存,调试阶段出错信息反馈等等 <sqlMap resource="com/user/user.xml" /> //////////////包含用户的相关操作xml文件 </sqlMapConfig>
User.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="User"> <typeAlias alias="user" type="com.user.User" /><!-- obj --> <!-- get user --> <select id="getUser" parameterClass="java.lang.String" resultClass="user"> <![CDATA[ select id, name, sex from t_user where name like #name# ]]> </select> <!-- update user --> <update id="updateUser" parameterClass="user"> <![CDATA[ update t_user set name=#name#, sex=#sex# where id = #id# ]]> </update> <insert id="insertUser" parameterClass="user"> <![CDATA[ insert into t_user( id, name, sex) values( #id#, #name#, #sex# ) ]]> </insert> <delete id="deleteUser" parameterClass="java.lang.String"> <![CDATA[ delete from t_user where id = #value# ]]> </delete> <select id="selectUser" resultClass="user"> <![CDATA[ select * from t_user order by id desc ]]> </select> </sqlMap>
该配置文件属性就不多了。用户可在网上搜一堆够看了。
针对spring_other.xml 里面的用户自定义bean如下
UserDao.java 接口
1. package com.user.dao; 2. 3. import java.util.List; 4. 5. import com.user.User; 6. 7. 8. public interface UserDao { 9. public User getUser(String name); 10. public void updateUser(User user); 11. public List selectUser(); 12. public void insertUser(User user);13. }
UserDaoImpl.java 实现类
14. package com.user.dao; 15. 16. import java.util.List; 17. 18. import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; 19. 20. import com.user.User; 21. 22. 23. public class UserDaoImpl extends SqlMapClientDaoSupport implements UserDao { 24. //private static Logger log = Logger.getLogger(UserDaoImpl.class); 25. public User getUser(String name) { 26. return (User) this.getSqlMapClientTemplate().queryForObject("User.getUser","name"); 27. } 28. 29. public void updateUser(User user) { 30. this.getSqlMapClientTemplate().update("User.updateUser", user); 31. } 32. 33. public List selectUser() { 34. return this.getSqlMapClientTemplate().queryForList("User.selectUser",""); 35. } 36. 37. public void insertUser(User user) { 38. this.getSqlMapClientTemplate().insert("User.insertUser", user); 39. }40. }
现在大家也许看到这里觉得就差不多了。该Dao方法差不多全了,可以进行操作了。其实不然,下面我载自官方的一段:
Spring提供两种方式的编程式事务管理,分别是:使用TransactionTemplate和直接使用PlatformTransactionManager。 ⅰ. TransactionTempale采用和其他Spring模板,如JdbcTempalte和HibernateTemplate一样的方法。它使用回调方法,把应用程序从处理取得和释放资源中解脱出来。如同其他模板,TransactionTemplate是线程安全的
所以我们下面我们要再封装一层以实现线程是安全的。这就是我们在spirng_other.xml里面的那段配置实现
baseService.java
package com.base; import org.springframework.transaction.support.TransactionTemplate; /** * 工厂的基础类. * @author 刘玉华 * @time 2007-12-14 */ public class BaseService extends TransactionTemplate{ private static final long serialVersionUID = 1L; } serviceFactory.java 41. package com.base; 42. 43. import org.springframework.beans.factory.BeanFactory; 44. import org.springframework.context.support.ClassPathXmlApplicationContext; 45. 46. import com.user.dao.UserDao; 47. 48. /** 49. * 数据操作工厂,所有的数据操作都从该工厂中获得。 50. * @author 刘玉华 51. * @time 2007-12-14 52. */ 53. 54. public class ServiceFactory { 55. private static BeanFactory factory = null; 56. 57. static { 58. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( 59. new String[] {"spring_base.xml"}); 60. factory = (BeanFactory) context; 61. } 62. 63. 64. 65. /** 66. * 获得用户服务类 67. * @return 用户服务 68. */ 69. public static UserDao getUserService(){ 70. return (UserDao) factory.getBean("userService"); 71. }72. }
我们所需要做的就是继承Baseservice.java 以实现tx管理
UserService.java
package com.user; import java.util.List; public interface UserService { public User getUser(final String name); public void updateUser(final User user); public List selectUser(); public void insertUser(final User user); }
UserServiceImpl.java 用户服务实现类
73. package com.user; 74. 75. import java.util.List; 76. 77. import org.springframework.transaction.TransactionStatus; 78. import org.springframework.transaction.support.TransactionCallback; 79. 80. import com.base.BaseService; 81. import com.user.dao.UserDao; 82. 83. public class UserServiceImpl extends BaseService implements UserDao { 84. private UserDao userDao; 85. 86. public UserDao getUserDao() { 87. return userDao; 88. } 89. 90. public void setUserDao(UserDao userDao) { 91. this.userDao = userDao; 92. } 93. 94. public List selectUser() { 95. Object obj = execute(new TransactionCallback(){ 96. public Object doInTransaction(TransactionStatus status) { 97. return userDao.selectUser(); 98. } 99. }); 100. return (List)obj; 101. } 102. 103. public User getUser(final String name){ 104. Object obj = execute(new TransactionCallback(){ 105. public Object doInTransaction(TransactionStatus status) { 106. // TODO Auto-generated method stub 107. return userDao.getUser(name); 108. } 109. }); 110. return (User) obj; 111. } 112. 113. public void insertUser(final User user) { 114. Object obj = execute(new TransactionCallback(){ 115. public Object doInTransaction(TransactionStatus status) { 116. userDao.insertUser(user); 117. return null; 118. } 119. }); 120. } 121. 122. public void updateUser(final User user) { 123. Object obj = execute(new TransactionCallback(){ 124. public Object doInTransaction(TransactionStatus arg0) { 125. userDao.updateUser(user); 126. return null; 127. } 128. }); 129. 130. }131. 132. }
这样我们就把相关操作实现事务控制了。
数据表建立:
create table t_user( "id" int null, "name" varchar(50) null, "sex" int null )
这样我们在以后调用方式为:
测试类
133. package com.user.junit; 134. 135. import java.util.List; 136. 137. import com.base.ServiceFactory; 138. import com.user.User; 139. import com.user.dao.UserDao; 140. import common.Logger; 141. 142. public class UserTest { 143. private static Logger log = Logger.getLogger(UserTest.class); 144. public static void main(String args[]){ 145. UserDao service = ServiceFactory.getUserService(); 146. User user=null; 147. int i = 4; 148. switch (i) { 149. case 0: 150. user.setId(1); 151. user.setName("444"); 152. user.setSex(2); 153. service.updateUser(user); 154. System.out.println(user.getName()+" "+user.getSex()); 155. break; 156. case 1: 157. try { 158. user = service.getUser("2"); 159. } catch (Exception e) { 160. log.debug("出错了"+e.getMessage()); 161. } 162. System.out.println(user.getId()); 163. case 3: 164. List<User> ls = service.selectUser(); 165. for (int j = 0; j < ls.size(); j++) { 166. System.out.println(ls.get(j).getId()+"===="+ls.get(j).getName()); 167. } 168. case 4: 169. List<User> ls1 = service.selectUser(); 170. for (int j = 0; j < ls1.size(); j++) { 171. user = ls1.get(j); 172. System.out.println(user.getId()+user.getName()+user.getSex()+user.getAddress()); 173. } 174. for (int j = 0; j < 100; j++) { 175. user.setId(user.getId()+1); 176. service.insertUser(user); 177. } 178. default: 179. break; 180. }181. }182. }
基本上差不多了。如果有需要源码的请联系我,FirstIbatis.zip 为整合serivce之后的 . FirstIbatis_no_service.zip 整合serivce之前的。