基于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之前的。