介紹java
iBATIS是以SQL爲中心的持久化層框架。能支持懶加載、關聯查詢、繼承等特性。mysql
iBATIS不一樣於通常的OR映射框架(eg:hibernate)。OR映射框架,將數據庫表、字段等映射到類、屬性,那是一種元數據(meta-data)映射。iBATIS則是將SQL查詢的參數和結果集映射到類。所以能夠說,iBATIS作的是SQL Mapping的工做。它把SQL語句當作輸入以及輸出,結果集就是輸出,而where後面的條件參數則是輸入。iBATIS能將輸入的普通POJO對象、Map、XML等映射到SQL的條件參數上,同時也能夠將查詢結果映射到普通POJO對象(集合)、Map、XML等上面。spring
iBATIS使用xml文件來映射這些輸入以及輸出。能大大減小數據庫存儲部分的代碼量,並且能夠很是方便的利用SQL中的一些小技巧。sql
簡單示例數據庫
基於ibatis-2.3.0.677版本。express
1、 建立新的項目,並引入jar包apache
a) ibatis-2.3.0.677.jar安全
b) mysql驅動session
2、 在類路徑中(classes下)提供ibatis的配置文件:sqlMapConfig.xmlapp
<?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> <transactionManager type="JDBC" commitRequired="false"> <dataSource type="SIMPLE"> <property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/> <property name="JDBC.ConnectionURL"value="jdbc:mysql://127.0.0.1/ibatis"/> <property name="JDBC.Username" value="root"/> <property name="JDBC.Password" value="mysql"/> </dataSource> </transactionManager> <sqlMap resource="com/ibatis/model/User.xml"/> </sqlMapConfig> |
3、建立實體類:User.java
package com.ibatis.model; publicclass User { privateintid; private String username; private String password;
publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getPassword() { returnpassword; } publicvoid setPassword(String password) { this.password = password; } public String getUsername() { returnusername; } publicvoid setUsername(String username) { this.username = username; } } |
4、建立針對User對象的CRUD的xml映射配置: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"> <!-- Use type aliases to avoid typing the full classname every time. --> <typeAlias alias="User" type="com.ibatis.model.User"/> <!-- Select with no parameters using the result map for Account class. --> <select id="selectAllUsers" resultClass="User"> select * from t_user </select>
<select id="selectUser" resultClass="User" parameterClass="int"> select * from t_user where id=#id# </select>
<insert id="insertUser" parameterClass="User"> insert into t_user values ( null,#username#,#password# ) </insert>
<update id="updateUser" parameterClass="User"> update t_user set username = #username#,password=#password# where id=#id# </update>
<delete id="deleteUser" parameterClass="int"> delete from t_user where id=#id# </delete> </sqlMap> |
5、建立測試程序測試:
package com.crm.model; import java.io.Reader; import java.util.Iterator; import java.util.List; import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; /** *最簡單的形式! *@authorq * */ publicclass UserTest { /** *@paramargs */ publicstaticvoid main(String[] args) throws Exception{ //從配置文件中獲得SqlMapClient對象 Reader reader = Resources.getResourceAsReader("sqlMapConfig.xml"); SqlMapClient sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader); reader.close();
//建立用戶數據 for(int i=0; i<10; i++){ User user = new User(); user.setUsername("用戶"+i); user.setPassword("密碼"+i); sqlMapper.insert("insertUser", user); }
//查詢用戶數據 List users = sqlMapper.queryForList("selectAllUsers"); for (Iterator iter = users.iterator(); iter.hasNext();) { User user = (User) iter.next(); System.out.println(user.getUsername()); }
//查詢特定用戶的數據 User user = (User)sqlMapper.queryForObject("selectUser", 1); System.out.println("用戶【id="+1+"】的名稱是:"+user.getUsername());
//更新用戶的信息 user = new User(); user.setId(3); user.setUsername("更改以後的用戶名稱"); user.setPassword("密碼被更改"); sqlMapper.update("updateUser", user);
//刪除用戶的信息 sqlMapper.delete("deleteUser", 6); } } |
這個對象是iBatis操做數據庫的接口(執行CRUD等操做),它也能夠執行事務管理等操做。這個類是咱們使用iBATIS的最主要的類。它是線程安全的。一般,將它定義爲單例。(與hibernate中sessionFactory的定義相似)。如:
import java.io.Reader; import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; public class IbatisSQLMapConfig { private static final SqlMapClient sqlMap; //在靜態區塊中初試化返回 static { try { //聲明配置文件的名稱(映射文件被定義在其中) String resource = "sql_map_config.xml"; //利用工具類Resources來讀取到配置文件 Reader reader = Resources.getResourceAsReader(resource); //建立SqlMapClient接口的變量實例 sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException( "Error initializing MyAppSqlConfig class. Cause: " + e); } } public static SqlMapClient getSqlMapInstance() { //提供靜態方法返回靜態區塊中獲得的SqlMapClient return sqlMap; } } |
如下全部虛線上面表明User.xml中的內容,虛線下方是測試類中的內容:User類沿用上一篇中的User類
<insert id="insertUser" parameterClass="User"> insert into t_user values ( null,#username#,#password# ) <selectKey resultClass="int" keyProperty="id"> SELECT @@IDENTITY AS ID </selectKey> </insert> |
User user = new User(); user.setUsername("張三"); user.setPassword("張三密碼");
//若是主鍵是自動生成的,則其返回值能夠經過<selectKey>標籤來設置 //若是不經過<selectKey>標籤來設置,則返回值爲空! //<selectKey >中的keyProperty,是指定User中的id屬性,當調用結束以後, //user對象的id值和insert方法的返回值都是這條記錄的ID值! Object obj = sqlMapper.insert("insertUser", user); |
<insert id="insertUser" parameterClass="User"> insert into t_user values ( null,#username#,#password# ) <selectKey resultClass="int" keyProperty="id"> SELECT @@IDENTITY AS ID </selectKey> </insert>
<insert id="insertUser2"> insert into t_user values ( null,#username#,#password# ) <selectKey resultClass="int" keyProperty="id"> SELECT @@IDENTITY AS ID </selectKey> </insert> |
insertUser使用了parameterClass,因此必需傳入User類型的對象
User user = new User(); user.setUsername("張三"); user.setPassword("張三密碼");
//傳遞進去的對象,必須是User類型 Object obj = sqlMapper.insert("insertUser", user); |
insertUser2沒有使用parameterClass,因此能夠傳入任意具備相應屬性值的對象
JustAnObject anobj = new JustAnObject(); anobj.setUsername("用戶名"); anobj.setPassword("用戶密碼");
//若是沒有指定parameterClass屬性,則任何一個具備相應屬性值 //的對象均可以被傳遞進去 Object obj = sqlMapper.insert("insertUser2", anobj); |
<parameterMap class="User" id="insertUser-param"> <parameter property="username"/> <parameter property="password"/> </parameterMap> <insert id="insertUser" parameterMap="insertUser-param"> insert into t_user values ( null,?,? ) <selectKey resultClass="int" keyProperty="id"> SELECT @@IDENTITY AS ID </selectKey> </insert> |
parameterMap用於傳入參數,以便匹配SQL語句中的?號
User user = new User(); user.setUsername("張三dd"); user.setPassword("張三密碼dd");
Object obj = sqlMapper.insert("insertUser", user); |
利用parameterMap,能夠定義參數對象的屬性如何映射到SQL查詢語句的動態參數上,注意parameterMap中<parameter/>標籤的前後順序不能顛倒!
package com.ibatis.model;
publicclassOtherObject {
privateintid;
private String prop1;
private String prop2;
publicint getId() {
returnid;
}
publicvoid setId(int id) {
this.id = id;
}
public String getProp1() {
return Prop1;
}
publicvoid set Prop1 (String Prop1) {
this. Prop1 = Prop1;
}
public String getProp2() {
returnusername;
}
publicvoid setProp2 (String Prop2) {
this.Prop2 = Prop2;
}
}
<select id="selectUserForOtherObject" resultClass="com. ibatis.OtherObject" parameterClass="int"> select username as prop1, password as prop2 from t_user where id=#value# </select> |
//查找t_user表,將其結果映射到一個屬性名不一樣的對象中! OtherObject obj = (OtherObject)sqlMapper.queryForObject("selectUserForOtherObject", 1); System.out.println(obj.getProp1()+","+obj.getProp2()); |
<resultMap class="com.ibatis.model.OtherObject" id="ooResult"> <result property="prop1" column="username"/> <result property="prop2" column="password"/> </resultMap> <!-- 若是使用resultMap來定義如何映射,則以下語句不可寫成: select username as prop1,password as prop2 .... --> <select id="selectUserForOtherObject2" parameterClass="int"resultMap="ooResult"> select username, password from t_user where id=#value# </select> |
//查找t_user表,將其結果映射到一個屬性名不一樣的對象中! OtherObject obj = (OtherObject)sqlMapper.queryForObject("selectUserForOtherObject2", 17); System.out.println(obj.getProp1()+","+obj.getProp2()); |
<select id="selectXmlData" resultClass="xml" xmlResultName="User"parameterClass="int"> select * from t_user where id=#value# </select> <select id="selectXmlDatas" resultClass="xml" xmlResultName="User"> select * from t_user </select> |
//查找t_user表,將其結果映射到xml! //返回值是xml形式的字符串 Object obj = (Object)sqlMapper.queryForObject("selectXmlData", 1); System.out.println(obj); //查找t_user表,將其結果映射到xml! List list = (List)sqlMapper.queryForList("selectXmlDatas"); System.out.println(list); |
<!-- 這裏,可使用全路徑類名,如: java.util.Map java.util.HashMap java.util.TreeMap 或 map --> <insert id="insertUser" parameterClass="map"> insert into t_user values ( null,#username#,#password# ) </insert> |
Map user = new TreeMap(); user.put("username", "Map用戶"); user.put("password", "Map用戶密碼"); sqlMapper.insert("insertUser",user); |
<!-- resultClass能夠定義爲java.util.HashMap類型, 將能自動轉換 --> <select id="selectMapUsers" resultClass="java.util.HashMap"> select * from t_user </select> |
List list = (List)sqlMapper.queryForList("selectMapUsers"); System.out.println(list); for (Iterator iter = list.iterator(); iter.hasNext();) { Map map = (Map) iter.next(); //可在此輸出map的數據 } |
可使用sqlMapClient的startTransaction/commitTransaction/endTransaction等方法來控制事務的邊界。
若是與spring整合(這是iBatis推薦的方式),則咱們須要在spring配置文件中指定其事務特性。
Spring經過DAO模式,提供了對iBATIS的良好支持。SqlMapClient對象是iBATIS中的主要對象,咱們能夠經過配置讓spring來管理SqlMapClient對象的建立。
與hibernate相似,Spring 提供了SqlMapClientDaoSupport對象,咱們的DAO能夠繼承這個類,經過它所提供的SqlMapClientTemplate對象來操縱數據庫。看起來這些概念都與hibernate相似。
經過SqlMapClientTemplate來操縱數據庫的CRUD是沒有問題的,這裏面關鍵的問題是事務處理。Spring提供了強大的聲明式事務處理的功能,咱們已經清楚hibernate中如何配置聲明式的事務,那麼在iBATIS中如何得到聲明式事務的能力呢?
第一,咱們須要瞭解的是spring經過AOP來攔截方法的調用,從而在這些方法上面添加聲明式事務處理的能力。典型配置以下:applicationContext-common.xml
<!-- 配置事務特性 --> <tx:advice id="txAdvice" transaction-manager="事務管理器名稱"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="del*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice>
<!-- 配置哪些類的方法須要進行事務管理 --> <aop:config> <aop:pointcut id="allManagerMethod" expression="execution(* com.ibatis.manager.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod"/> </aop:config> |
這些事務都是聲明在業務邏輯層的對象上的。
第二,咱們須要一個事務管理器,對事務進行管理。
<bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1/ibatis"/> <property name="username" value="root"/> <property name="password" value="mysql"/> </bean> |
此後,咱們須要讓spring來管理SqlMapClient對象:
<bean id="sqlMapClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"><value>classpath:sqlMapConfig.xml</value></property> </bean> |
咱們的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
lazyLoadingEnabled="true"
useStatementNamespaces="true" />
<!-- 使用spring以後,數據源的配置移植到了spring上,因此iBATIS自己的配置能夠取消 -->
<sqlMap resource="com/ibatis/dao/impl/ibatis/User.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">
<!-- Use type aliases to avoid typing the full classname every time. -->
<typeAlias alias="User" type="com.ibatis.User"/>
<!-- Select with no parameters using the result map for Account class. -->
<select id="selectAllUsers" resultClass="User">
select * from t_user
</select>
<select id="selectUser" resultClass="User" parameterClass="int">
select * from t_user where id=#id#
</select>
<insert id="insertUser" parameterClass="User">
insert into t_user values (
null,#username#,#password#
)
</insert>
<update id="updateUser" parameterClass="User">
update t_user set username = #username#,password=#password#
where id=#id#
</update>
<delete id="deleteUser" parameterClass="int">
delete from t_user where id=#id#
</delete>
</sqlMap>
咱們的DAO的編寫:
package com.iabtis.dao.impl.ibatis; import java.util.List; import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; import com.ibatis.dao.UserDAO; import com.ibatis.crm.model.User; public class UserDAOImpl extends SqlMapClientDaoSupport implements UserDAO { public User select(User user) { return getSqlMapClientTemplate().querForObject("selectUser ",user.getId()); } public List findAll() { return getSqlMapClientTemplate().queryForList("selectAllUsers "); } public void delete(User user) { getSqlMapClientTemplate().delete("deleteUser ",user.getId()); } public void save(User user) { getSqlMapClientTemplate().insert("insertUser ",user); } public void update(User user) { getSqlMapClientTemplate().update("updateUser ",user); } } |
繼承SqlMapClientDaoSupport,要求咱們注入SqlMapClient對象,所以,須要有以下的DAO配置:
<bean id="userDAO" class="com.ibatils.dao.impl.ibatis.UserDAOImpl"> <property name=」sqlMapClient」 ref=」sqlMapClient」/> </bean> |
這就是全部須要注意的問題了,此後就能夠在業務邏輯層調用DAO對象了!