在2010年6月16日,iBATIS团队决定从apache迁出并迁移到Google Code,并更名为MyBatis。目前iBATIS 2.x和MyBatis 3不是100%兼容的,如配置文件的DTD变更,SqlMapClient直接由SqlSessionFactory代替了,包名也有com.ibatis变成org.ibatis等等。
ibatis 3.x和MyBatis是兼容的,只需要将DTD变更一下就可以了。
当前在MyBatis之前,我们一直用的都是ibatis,这里先介绍spring对ibatis的集成。
一:Spring整合ibatis
spring整合ibatis首先需要导入相关jar包:
spring-orm-3.2.0.RELEASE.jar (提供SqlMapClientFactoryBean,SqlMapClientDaoSupport等类。遗憾的是spring自3.2.*版本之后已经废弃了
SqlMapClientDaoSupport。)
mybatis-2.3.5.jar (提供com.ibatis.sqlmap.client.SqlMapClient类)
项目结构如下:
首先是配置文件配置,ibatis的总配置文件
sqlMapConfig.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 cacheModelsEnabled="false" enhancementEnabled="true" lazyLoadingEnabled="true" maxRequests="64" maxSessions="32" maxTransactions="16"
useStatementNamespaces="false"/>
<!--引入映射的文件-->
<sqlMap resource="sqlMap/account.xml"/>
</sqlMapConfig>
在sqlMapConfig.xml中引入了表和Vo的映射文件
account.xml:
其中account表的表结构如下:
AccountVo如下:
public class AccountVo implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String accountName;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", accountName=" + accountName + ", money=" + money + "]";
}
}
account.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="flysunAccountVo">
<typeAlias type="fly.sun.demo1.AccountVo" alias="accountVo" />
<resultMap class="accountVo" id="accountVo">
<result property="id" column="id" />
<result property="accountName" column="name" />
<result property="money" column="money" />
</resultMap>
<sql id="account_field_sql">
<!-- 这里的字段都是数据库中对应的字段名称 -->
a.id, a.name, a.money
</sql>
<!-- 根据id查询账户信息 -->
<select id="getAccountById" parameterClass="map" resultMap="accountVo">
/* getAccountById */
select <include refid="account_field_sql"/>
from account a where a.id = #id#
</select>
</sqlMap>
然后在spring的配置文件
applicationContext.xml文件中向SqlMapClientFactoryBean中注入配置文件和数据源,当然数据源也可以不在这里注入,在配置具体的dao层的bean时,在dao中注入数据源也可以。下面是applicationContext.xml的配置:
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="sqlMapClientFactoryBean" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>classpath:ibatis/sqlMapConfig.xml</value>
</property>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="fly.sun.demo1.AccountDaoImpl">
<!-- 此处不需要再配置数据源了,在"sqlMapClientFactoryBean"已经配置过了,如果accountDao中用的不是上面的dataSource,再单独配置 -->
<!-- <property name="dataSource" ref=""/> -->
</bean>
<bean id="accountService" class="fly.sun.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
</beans>
这样所有的配置就结束了,剩下的是在Dao中继承Spring对ibatis提供的Dao操作的模板类SqlMapClientDaoSupport。通常开发中的做法是写成一个BaseDao来继承这个类。然后让每一个需要的Dao再继承BaseDao就可以了。原因是因为在BaseDao中我们需要给
SqlMapClientDaoSupport注入SqlMapClientFactoryBean的实例SqlMapClient,这样在父类BaseDao中注入一次就可以了。不然每个Dao都需要注入显得很繁琐。直接上代码:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import com.ibatis.sqlmap.client.SqlMapClient;
public class BaseDao extends SqlMapClientDaoSupport implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
// 给dao注入 sqlMapClient bean
SqlMapClient sqlMapClient = (SqlMapClient) beanFactory.getBean("sqlMapClientFactoryBean");
//调用SqlMapClientDaoSupport中的setSqlMapClient方法
setSqlMapClient(sqlMapClient);
}
}
这样我的AccountDaoImpl继承这个BaseDao:
import java.util.HashMap;
import java.util.Map;
public class AccountDaoImpl extends BaseDao implements AccountDao {
@Override
public AccountVo getAccountById(int id) {
Map<String, Object> params = new HashMap<String, Object>(1, 1F);
params.put("id", id);
return (AccountVo) this.getSqlMapClientTemplate().queryForObject("getAccountById", params);
}
}
AccountServiceImpl如下:
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public AccountVo getAccountById(int id) {
return accountDao.getAccountById(id);
}
}
测试类如下:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class MyTest {
@Autowired
private AccountService accountService;
@Test
public void test(){
AccountVo account = accountService.getAccountById(1);
System.out.println(account);
}
}
结果打印如下:
这样一个完成spring整合ibatis就已经大功告成了。
(备注):
在上面的测试过程中,所有的Dao都是通过继承BaseDao来完成工作的,这里介绍下直接用Dao继承SqlMapClientDaoSupport的操作方法。其他内容不变,改动点如下:(Dao层直接继承SqlMapClientDaoSupport)
然后applicationContext.xml配置文件也稍微要改下,通过bean中的parent属性来给SqlMapClientDaoSupport注入SqlMapClient实例。这样每个dao只需要配置下parent属性就行了,不用每个dao都注入sqlMapClient属性。
不过你要是喜欢这样每次Dao里面单独注入也可以: