基于Spring+Ibatis的安全线程实现
过去做过一些基于spring、hibernate整合应用的实例,本人感觉spring与hibernate最好的结合就是泛型Dao的实现,代码量节省了一半,而且业务逻辑一目了然。
后来做别的系统时候考虑过这样的框架,但是数据库结构如果不固定,动态生成的东西比较多这个时候只好放弃了hibernate而选择了同样具有orm性能的ibatis,下面就spring与ibatis的结合相关配置做下说明(如有不同意见,希望交流)
首先spring和ibatis具体下载和安装就不多说了。直接切入正题
Spring框架下的ibatis应用,特别是在容器事务管理模式下的ibatis应用开发
部署如下:
首先spring配置文件:
view plaincopy to clipboardprint?
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 <A title=sql href="http://www.google.cn/search?sbi=sql&q=sql&sbb=搜索&sa=搜索&client=pub-6430022987645146&forid=1&prog=aff&ie=GB2312&oe=GB2312&hl=zh-CN" target=_blank>sql</A> 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 <A title=sql href="http://www.google.cn/search?sbi=sql&q=sql&sbb=搜索&sa=搜索&client=pub-6430022987645146&forid=1&prog=aff&ie=GB2312&oe=GB2312&hl=zh-CN" target=_blank>sql</A> 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 接口
package com.user.dao;
import java.util.List;
import com.user.User;
public interface UserDao {
public User getUser(String name);
public void updateUser(User user);
public List selectUser();
public void insertUser(User user);
}
UserDaoImpl.java 实现类
package com.user.dao;
import java.util.List;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import com.user.User;
public class UserDaoImpl extends SqlMapClientDaoSupport implements UserDao {
//private static Logger log = Logger.getLogger(UserDaoImpl.class);
public User getUser(String name) {
return (User) this.getSqlMapClientTemplate().queryForObject("User.getUser","name");
}
public void updateUser(User user) {
this.getSqlMapClientTemplate().update("User.updateUser", user);
}
public List selectUser() {
return this.getSqlMapClientTemplate().queryForList("User.selectUser","");
}
public void insertUser(User user) {
this.getSqlMapClientTemplate().insert("User.insertUser", user);
}
}
现在大家也许看到这里觉得就差不多了。该Dao方法差不多全了,可以进行操作了。其实不然,下面我载自官方的一段:
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 接口
package com.user.dao;
import java.util.List;
import com.user.User;
public interface UserDao {
public User getUser(String name);
public void updateUser(User user);
public List selectUser();
public void insertUser(User user);
}
UserDaoImpl.java 实现类
package com.user.dao;
import java.util.List;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import com.user.User;
public class UserDaoImpl extends SqlMapClientDaoSupport implements UserDao {
//private static Logger log = Logger.getLogger(UserDaoImpl.class);
public User getUser(String name) {
return (User) this.getSqlMapClientTemplate().queryForObject("User.getUser","name");
}
public void updateUser(User user) {
this.getSqlMapClientTemplate().update("User.updateUser", user);
}
public List selectUser() {
return this.getSqlMapClientTemplate().queryForList("User.selectUser","");
}
public void insertUser(User user) {
this.getSqlMapClientTemplate().insert("User.insertUser", user);
}
}
现在大家也许看到这里觉得就差不多了。该Dao方法差不多全了,可以进行操作了。其实不然,下面我载自官方的一段:
Spring提供两种方式的编程式事务管理,分别是:使用TransactionTemplate和直接使用PlatformTransactionManager。
ⅰ.
TransactionTempale采用和其他Spring模板,如JdbcTempalte和HibernateTemplate一样的方法。它使用回调方法,把应用程序从处理取得和释放资源中解脱出来。如同其他模板,TransactionTemplate是线程安全的
view plaincopy to clipboardprint?
所以我们下面我们要再封装一层以实现线程是安全的。这就是我们在spirng_other.xml里面的那段配置实现
所以我们下面我们要再封装一层以实现线程是安全的。这就是我们在spirng_other.xml里面的那段配置实现view plaincopy to clipboardprint?
<PRE class=csharp name="code">baseService.java
package com.base;
import org.springframework.transaction.support.TransactionTemplate;
/**
* 工厂的基础类.
* @author 刘玉华
* @time <A title=2007 href="http://www.google.cn/search?sbi=基金&amp;q=基金&amp;sbb=搜索&amp;sa=搜索&amp;client=pub-6430022987645146&amp;forid=1&amp;prog=aff&amp;ie=GB2312&amp;oe=GB2312&amp;hl=zh-CN" target=_blank>2007</A>-12-14
*/
public class BaseService extends TransactionTemplate{
private static final long serialVersionUID = 1L;
}
serviceFactory.java
package com.base;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.user.dao.UserDao;
/**
* 数据操作工厂,所有的数据操作都从该工厂中获得。
* @author 刘玉华
* @time <A title=2007 href="http://www.google.cn/search?sbi=基金&amp;q=基金&amp;sbb=搜索&amp;sa=搜索&amp;client=pub-6430022987645146&amp;forid=1&amp;prog=aff&amp;ie=GB2312&amp;oe=GB2312&amp;hl=zh-CN" target=_blank>2007</A>-12-14
*/
public class ServiceFactory {
private static BeanFactory factory = null;
static {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {"spring_base.xml"});
factory = (BeanFactory) context;
}
/**
* 获得用户服务类
* @return 用户服务
*/
public static UserDao getUserService(){
return (UserDao) factory.getBean("userService");
}
}
我们所需要做的就是继承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 用户服务实现类
package com.user;
import java.util.List;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import com.base.BaseService;
import com.user.dao.UserDao;
public class UserServiceImpl extends BaseService implements UserDao {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public List selectUser() {
Object obj = execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus status) {
return userDao.selectUser();
}
});
return (List)obj;
}
public User getUser(final String name){
Object obj = execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus status) {
// TODO Auto-generated method stub
return userDao.getUser(name);
}
});
return (User) obj;
}
public void insertUser(final User user) {
Object obj = execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus status) {
userDao.insertUser(user);
return null;
}
});
}
public void updateUser(final User user) {
Object obj = execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus arg0) {
userDao.updateUser(user);
return null;
}
});
}
}
这样我们就把相关操作实现事务控制了。
数据表建立:
create <A title=table href="http://www.alimama.com/membersvc/buyadzone/buy_ad_zone.htm?adzoneid=892989 " target=_blank>table</A> t_user(
"id" int null,
"name" varchar(50) null,
"sex" int null
)
这样我们在以后调用方式为:
测试类
package com.user.junit;
import java.util.List;
import com.base.ServiceFactory;
import com.user.User;
import com.user.dao.UserDao;
import common.Logger;
public class UserTest {
private static Logger log = Logger.getLogger(UserTest.class);
public static void main(String args[]){
UserDao service = ServiceFactory.getUserService();
User user=null;
int i = 4;
switch (i) {
case 0:
user.setId(1);
user.setName("444");
user.setSex(2);
service.updateUser(user);
<A title=system href="http://www.alimama.com/membersvc/buyadzone/buy_ad_zone.htm?adzoneid=892989 " target=_blank>system</A>.out.println(user.getName()+" "+user.getSex());
break;
case 1:
try {
user = service.getUser("2");
} catch (Exception e) {
log.debug("出错了"+e.getMessage());
}
<A title=system href="http://www.alimama.com/membersvc/buyadzone/buy_ad_zone.htm?adzoneid=892989 " target=_blank>system</A>.out.println(user.getId());
case 3:
List<User> ls = service.selectUser();
for (int j = 0; j < ls.size(); j++) {
<A title=system href="http://www.alimama.com/membersvc/buyadzone/buy_ad_zone.htm?adzoneid=892989 " target=_blank>system</A>.out.println(ls.get(j).getId()+"===="+ls.get(j).getName());
}
case 4:
List<User> ls1 = service.selectUser();
for (int j = 0; j < ls1.size(); j++) {
user = ls1.get(j);
<A title=system href="http://www.alimama.com/membersvc/buyadzone/buy_ad_zone.htm?adzoneid=892989 " target=_blank>system</A>.out.println(user.getId()+user.getName()+user.getSex()+user.getAddress());
}
for (int j = 0; j < 100; j++) {
user.setId(user.getId()+1);
service.insertUser(user);
}
default:
break;
}
}
}
</PRE>