项目采用的是struts2的+弹簧+ ibatis的架构,下面是关键部分代码:
applicationContext.xml中:
<b>[html] </b>查看纯文本
<?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:context = “http://www.springframework.org/schema/context”
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/context
http://www.springframework.org/schema/context/spring-context-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“
default-autowire = “byName” default-lazy-init = “false” >
< context:component-scan base-package = “com.ssi。*” />
<! - 属性文件读入 - >
< bean id = “propertyConfigurer” class = “org.springframework.beans.factory.config.PropertyPlaceholderConfigurer” >>
< property name = “locations” >
< list >
< value > classpath *:jdbc.properties </ value >
</ list >
</ property >
</ bean >
<! - 配置sqlMapclient - >
< bean id = “sqlMapClient” class = “org.springframework.orm.ibatis.SqlMapClientFactoryBean” >
< property name = “configLocation” value = “classpath:ibatis-sqlmap-config.xml” />
< property name = “dataSource” ref = “dataSource” />
< bean id = “sqlMapClient1” class = “org.springframework.orm.ibatis.SqlMapClientFactoryBean” >
< property name = “dataSource” ref = “db1” />
< bean id = “sqlMapClient2” class = “org.springframework.orm.ibatis.SqlMapClientFactoryBean” >
< property name = “dataSource” ref = “db2” />
< bean id = “sqlMapClientCenter” class = “org.springframework.orm.ibatis.SqlMapClientFactoryBean” >
< property name = “dataSource” ref = “center” />
< bean id = “dynamicSqlMapClientDaoSupport” class = “com.ssi.dao.DynamicSqlClientDaoSupport” >>
< property name = “targetSqlMapClients” >
< map >
< entry key = “db1” value-ref = “sqlMapClient1” />
< entry key = “db2” value-ref = “sqlMapClient2” />
< entry key = “center” value-ref = “sqlMapClientCenter” />
</ map >
< property name = “defaultSqlMapClient” ref = “sqlMapClientCenter” />
< bean id = “ibatisDaoSupport” class = “com.ssi.dao.IbatisDaoSupport” parent = “dynamicSqlMapClientDaoSupport” > </bean >
< bean id = “userDao” class = “com.ssi.dao.impl.UserDaoImpl” parent = “ibatisDaoSupport” > </ bean >
<! - 支持@AspectJ标记 - >
< aop:aspectj-autoproxy proxy-target-class = “true” />
<! - 配置JTA的事务管理器 - >
< bean id = “atomikosTransactionManager” class = “com.atomikos.icatch.jta.UserTransactionManager” init-method = “init” destroy-method = “close” >
< property name = “forceShutdown” value = “true” />
< bean id = “atomikosUserTransaction” class = “com.atomikos.icatch.jta.UserTransactionImp” >
< property name = “transactionTimeout” value = “300” />
< bean id = “springTransactionManager” class = “org.springframework.transaction.jta.JtaTransactionManager”>
< property name = “transactionManager” ref = “atomikosTransactionManager” />
< property name = “userTransaction” ref = “atomikosUserTransaction” />
<! - 配置通知 - >
< tx:advice id = “txAdvice” transaction-manager = “springTransactionManager” >
< tx:attributes >
< tx:method name = “*” rollback-for = “Exception,RuntimeException,com.ssi.exception.SystemException” propagation = “REQUIRED” />
</ tx:attributes >
</ tx:advice >
<! - 以AspectJ方式定义AOP - >
< aop:config >
< aop:advisor pointcut = “execution(* com.ssi.service .. * Service *。*(..))” advice-ref = “txAdvice”/>
</ aop:config >
<! - spring定时器任务开始 - >
< bean name = “job” class = “org.springframework.scheduling.quartz.JobDetailBean” >
< property name = “jobClass” >
< value > com.ssi.action.TimerAction </ value >
</ property >
< property name = “jobDataAsMap” >
< map >
<! - timeout属性设定了当服务器启动后过10秒钟首次调用你的JobAction - >
< entry key = “timeout” >
< value > 10 </ value >
</ entry >
</ map >
< bean id = “cronTrigger” class = “org.springframework.scheduling.quartz.CronTriggerBean” >
< property name = “jobDetail” >
< ref bean = “job” />
< property name = “cronExpression” >
< 值> 0 53 15?* MON-FRI </ value >
< bean class = “org.springframework.scheduling.quartz.SchedulerFactoryBean” autowire = “no” >
< property name = “triggers” >
< list >
< ref local = “cronTrigger” />
</ list >
<! - spring定时器任务结束 - >
</ beans >
的applicationContext-datasource.xml
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-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd“ >
<! - 指定春天配置中用到的属性文件 - >
< bean id = “propertyConfig” class = “org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>>
< value > classpath:jdbc.properties </ value >
<! - JTA数据源配置 - >
< bean id = “center” class = “com.atomikos.jdbc.AtomikosDataSourceBean” init-method = “init” destroy-method = “close” >
< property name = “uniqueResourceName” >
< 值> mysql / center </ value >
< property name = “xaDataSourceClassName” >
< value > $ {jta.driver.className} </ value >
< property name = “xaProperties” >
< 道具>
< prop key = “url” > $ {center.jdbc.driver.url} </ prop >
< prop key = “user” > $ {center.sql.user.name} </ prop >
< prop key = “password” > $ {center.sql.user.password} </ prop >
</ 道具>
< property name = “testQuery” value = “select 1” />
< property name = “poolSize” >
< value > $ {poolsize} </ value >
< property name = “maxPoolSize” >
< value > $ {maxPoolSize} </ value >
< property name = “borrowConnectionTimeout” > < value > $ {borrowConnectionTimeout} </ value > </ property >
< bean id = “db1” class = “com.atomikos.jdbc.AtomikosDataSourceBean” init-method = “init” destroy-method = “close”>
< value > mysql / db1 </ value >
< prop key = “url” > $ {db1.jdbc.driver.url} </ prop >
< prop key = “user” > $ {company.sql.user.name} </ prop >
< prop key = “password” > $ {company.sql.user.password} </ prop >
< bean id = “db2” class = “com.atomikos.jdbc.AtomikosDataSourceBean” init-method = “init” destroy-method = “close”>
< value > mysql / db2 </ value >
< prop key = “url” > $ {db2.jdbc.driver.url} </ prop >
< bean id = “dataSource” class = “com.ssi.datasource.DynamicDataSource” >
< property name = “targetDataSources” >
< map key-type = “java.lang.String” >
< entry key = “db1” value-ref = “db1” />
< entry key = “db2” value-ref = “db2” />
< entry key = “center” value-ref = “center” />
< property name = “defaultTargetDataSource” ref = “center” />
DynamicSqlClientDaoSupport.java
<b>[java] </b>查看纯文本
包 com.ssi.dao;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.support.DaoSupport;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.util.Assert;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ssi.datasource.DbContextHolder;
公共类 DynamicSqlClientDaoSupport 扩展 DaoSupport 实现 InitializingBean {
私人 SqlMapClientTemplate sqlMapClientTemplate = 新的 SqlMapClientTemplate();
私人 地图<String,SqlMapClient> targetSqlMapClients;
私人 SqlMapClient的defaultSqlMapClient;
private boolean externalTemplate = false ;
/ **
*设置此DAO使用的JDBC数据源。
*不需要:SqlMapClient可能携带共享数据源。
* @see #setSqlMapClient
* /
public final void setDataSource(DataSource dataSource){
如果 (!this .externalTemplate){
这个.sqlMapClientTemplate.setDataSource(dataSource);
}
}
*返回此DAO使用的JDBC数据源。
public final DataSource getDataSource(){
返回这个.sqlMapClientTemplate.getDataSource();
*设置iBATIS数据库层SqlMapClient使用。
*这个或者“sqlMapClientTemplate”是必需的。
* @see #setSqlMapClientTemplate
public final void setSqlMapClient(SqlMapClient sqlMapClient){
这个.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
*返回该模板使用的iBATIS数据库层SqlMapClient。
public final SqlMapClient getSqlMapClient(){
返回这个.sqlMapClientTemplate.getSqlMapClient();
*明确地为此DAO设置SqlMapClientTemplate,
*作为指定SqlMapClient的替代方法。
public final void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate){
Assert.notNull(sqlMapClientTemplate, “SqlMapClientTemplate不能为空” );
这个.sqlMapClientTemplate = sqlMapClientTemplate;
这个.externalTemplate = true ;
*返回此DAO的SqlMapClientTemplate,
*用SqlMapClient预先初始化或明确设置。
public final SqlMapClientTemplate getSqlMapClientTemplate(){
字符串dbtype = DbContextHolder.getDbType();
if (targetSqlMapClients!= null && targetSqlMapClients.containsKey(dbtype)){
SqlMapClient sqlMapClient = targetSqlMapClients.get(dbtype);
sqlMapClientTemplate = 新的 SqlMapClientTemplate(sqlMapClient);
}
返回这个.sqlMapClientTemplate;
@覆盖
protected final void checkDaoConfig(){
这个.sqlMapClientTemplate.afterPropertiesSet();
public Map <String,SqlMapClient> getTargetSqlMapClients(){
返回 targetSqlMapClients;
public void setTargetSqlMapClients(Map <String,SqlMapClient> targetSqlMapClients){
这个.targetSqlMapClients = targetSqlMapClients;
public SqlMapClient getDefaultSqlMapClient(){
返回 defaultSqlMapClient;
public void setDefaultSqlMapClient(SqlMapClient defaultSqlMapClient){
这个.defaultSqlMapClient = defaultSqlMapClient;
}
IbatisDaoSupport.java
import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.ibatis.SqlMapClientCallback;
import com.ibatis.sqlmap.client.SqlMapExecutor;
@SuppressWarnings (“未选中” )
公共类 IbatisDaoSupport <实体> 扩展 DynamicSqlClientDaoSupport 实现 IEntityDao <实体> {
受保护的最终 日志日志= LogFactory.getLog(getClass());
公共 实体get(String sqlId,Serializable id){
return (Entity)getSqlMapClientTemplate()。queryForObject(sqlId,id);
公共 实体getByParamMap(字符串sqlId,对象参数){
return (Entity)getSqlMapClientTemplate()。queryForObject(sqlId,param);
public Object save(String sqlId,Object o){
返回 getSqlMapClientTemplate()。insert(sqlId,o);
public Object batchSave(final String sqlId,final List <Entity> entityList) throws Exception {
//执行回调
返回 getSqlMapClientTemplate()。execute(新的 SqlMapClientCallback(){
//实现回调接口
公共 对象doInSqlMapClient(SqlMapExecutor执行器) throws SQLException {
//开始批处理
executor.startBatch();
for (Entity entity:entityList){
executor.insert(sqlId,entity);
}
return executor.executeBatch();
}
});
public Integer remove(String sqlId,Object o){
返回 getSqlMapClientTemplate()。delete(sqlId,o);
public Integer removeById(String sqlId,Serializable id){
返回 getSqlMapClientTemplate()。delete(sqlId,id);
public Integer update(String sqlId,Object o){
返回 getSqlMapClientTemplate()。update(sqlId,o);
public long totalCount(String sqlId,Object o){
return (Long)getSqlMapClientTemplate()。queryForObject(sqlId,o);
public List <Entity> pagedList(String sqlId,Map <String,Object> map,int pageSize, int pageNum){
int start =(pageNum - 1 )* pageSize;
map.put(“开始” ,开始);
map.put(“pageSize” ,pageSize);
List <Entity> list = getSqlMapClientTemplate()。queryForList(sqlId,map);
退货 清单;
public List <Entity> list(String sqlId,Object o){
返回 getSqlMapClientTemplate()。queryForList(sqlId,o);
public List <Entity> list(String sqlId){
返回 getSqlMapClientTemplate()。queryForList(sqlId);
UserDaoImpl.java:
包 com.ssi.dao.impl;
import org.springframework.stereotype.Repository;
import com.ssi.dao.IUserDao;
import com.ssi.dao.IbatisDaoSupport;
import com.ssi.model.User;
@Repository (“userDAO的” )
公共类 UserDaoImpl 扩展 IbatisDaoSupport <用户> 实现 IUserDao {
公共 整数addUser(用户用户) 抛出 异常{
返回 (整数) 这个.save(“User.insert” ,用户);
UserServiceImpl.java
包 com.ssi.service.impl;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.ssi.service.IUserService;
@Service (“userService” )
公共类 UserServiceImpl 实现 IUserService {
@Resource private IUserDao userDao;
*测试在服务中切换数据源异常是否回滚
公共无效 addUser(用户用户) 抛出 异常{
DbContextHolder.setDbType(“db1” );
userDao.addUser(用户);
DbContextHolder.setDbType(“db2” );
user.setUserName(“user2” );
DbContextHolder.setDbType(“center” );
user.setUserName(“user3” );
//System.out.println(1/0);
DynamicDataSource.java:
public class DynamicDataSource extends AbstractRoutingDataSource {
静态 记录仪日志= Logger.getLogger(DynamicDataSource。类);
protected Object determineCurrentLookupKey(){
返回 DbContextHolder.getDbType();
DbContextHolder.java:
公共类 DbContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal();
public static void setDbType(String dbType){
contextHolder.set(DBTYPE);
public static String getDbType(){
return (String)contextHolder.get();
public static void clearDbType(){
contextHolder.remove();
三个数据库:dbcenter,db1,db2表结构均相同
脚本:
<b>[sql] </b>查看纯文本
DROP TABLE IF EXISTS`tb_user`;
CREATE TABLE `tb_user`(
`id` int (11) NOT NULL AUTO_INCREMENT,
`userName` varchar (20) DEFAULT NULL ,
` 密码` VARCHAR (60) DEFAULT NULL ,
PRIMARY KEY (`id`)
)ENGINE = InnoDB DEFAULT CHARSET = utf8;
单元测试:
公共类 JunitTest {
public ApplicationContext cxt;
@测试
公共无效的 init() 抛出 异常{
cxt = new ClassPathXmlApplicationContext(new String [] { “applicationContext.xml” ,“applicationContext-datasource.xml” });
testInsertUser();
私人无效 testInsertUser() 抛出 异常{
IUserService userService =(IUserService)cxt.getBean(“userService” );
用户用户= 新 用户();
user.setUserName(“user1” );
user.setPassword(“0” );
userService.addUser(用户);
私人无效 testInsertUser2() 抛出 异常{