項目采用的是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() 抛出 異常{