Spring:
1)Ioc
2)AOP
3)BeanFactory, DI
4)DispatcherServlet: handlerMapping,return ModelAndView,viewResolver
Struts:
1)ActionServlet
2)Struts-config.xml: FormBean,ActionMapping
3)Action.execute(),return ActionForward.
ibatis:
<beans>
<bean id="sqlMapTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlMapTransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="sqlMapTransactionManager"/>
</bean>
<!--sql map -->
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="com/mydomain/data/SqlMapConfig.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" name="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@10.1.5.11:1521:XE"/>
<property name="username" value="junshan"/>
<property name="password" value="junshan"/>
<property name="maxActive" value="20"/>
</bean>
<bean id="accountDAO" class="com.mydomain.AccountDAO">
<property name="sqlMapClient" ref="sqlMapClient"/>
<property name="sqlMapTransactionTemplate" ref="sqlMapTransactionTemplate"/>
</bean>
</beans>
public class SimpleTest {
public static void main(String[] args) {
ApplicationContext factory =
new ClassPathXmlApplicationContext("/com/mydomain/data/applicationContext.xml");
final AccountDAO accountDAO = (AccountDAO) factory.getBean("accountDAO");
final Account account = new Account();
account.setId(1);
account.setFirstName("tao");
account.setLastName("bao");
account.setEmailAddress("[email protected]");
account.setDate(new Date());
try {
accountDAO.getSqlMapTransactionTemplate().execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus status){
try{
accountDAO.deleteAccount(account.getId());
accountDAO.insertAccount(account);
//account.setLastName("bobo");
//accountDAO.updateAccount(account);
Account result = accountDAO.selectAccount(account);
System.out.println(result);
return null;
} catch (Exception e) {
status.setRollbackOnly();
return false;
}
}
});
//accountDAO.getSqlMapClient().commitTransaction();
} catch (Exception e) {
e.printStackTrace();
}
}
}
关于spring+ibatis sharding方案的实现:
1)根据ID和路由规则确定TargetDataSource
因为一般DaoImpl会下面这样实现,因此可以写一个类ShardSqlMapClientDaoSupport继承SqlMapClientDaoSupport,然后根据ID和路由规则确定TargetDataSource,调用setDataSource(TargetDataSource)方法。这样数据源的路由问题(就是分库)就解决了。
2)接下来看怎么实现sql中的分表。
a 首先根据id和路由规则确定表名table
b 因为如下面代码所示SqlMapClientTemplate的insert和queryForObject等方法都是通过callback来做的,这里只传一个statementName过去,具体的跟statement替换变量相关的代码都在ibatis包里,所以这里替换表名的工作还不是很好做。
c 那怎么办呢?通过搜索看到ibatis从3.0开始提供了Plugin接口,可以对执行的sql进行拦截,这样就可以把表名根据规则替换上去了。但是由于我们使用的是ibatis早期版本,升级的代价比较大,因此最后只在某些新项目使用了这个分表逻辑。
关于Plugin怎么使用看我的收藏夹最新文章。
3)如果查询条件中不含id,比如根据name查或动态条件查,特别是可能还需要分页,排序,group by,count等会比较麻烦,这种情况只能把sql发送到各个dataSource然后在应用端进行Merge。 没办法,Sharding是有代价的。
package com.lanp.dao;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import com.lanp.beans.Student;
public class StudentDaoImpl extends SqlMapClientDaoSupport implements StudentDao {
@Override
public Student getStudent(String name) {
try{
return (Student)getSqlMapClientTemplate().queryForObject("queryStudentById", name);
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
}
public Object queryForObject(final String statementName, final Object parameterObject)
throws DataAccessException {
return execute(new SqlMapClientCallback() {
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
return executor.queryForObject(statementName, parameterObject);
}
});
}
public Object insert(final String statementName, final Object parameterObject)
throws DataAccessException {
return execute(new SqlMapClientCallback() {
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
return executor.insert(statementName, parameterObject);
}
});
}