1.ibatis基礎理論知識
半自動化java持久層框架,開源免費,核心還是JDBC,只是將其封裝,減少了重複代碼的書寫(據某個閒的夠嗆的外國人統計,減少了62%的代碼),在編碼上更符合面向對象原理。
-----------
|——什麼是持久層: ----先說持久:持久就是把數據保存到可掉電式存儲設備中以備後續使用。(從內存保存到磁盤,加以固化) --通過關係型數據庫來完成。
----持久層:在系統邏輯層面上,專注於實現數據持久化的一個相對獨立的領域。“層”表示了應該有一個相對獨立的邏輯層面,而不是“模塊/ 單元”,應該有一個較爲清晰和嚴格的邏輯邊界。
————
|______什麼是半自動化: 因爲ibatis還要程序員自己編寫訪問數據庫的sql語句。 ------{提高了可控性,但是當數據庫設計改變時,ibatis配置文件中的sql也要隨之更改。}
2.ibatis的特點
優點:
1) 簡單,配置文件只有兩個jar包: 一個是ibatis本身的jar包,一個是連接數據庫的jar包
2)關注點分離: 使用ibatis,使用與對象打交道,不會有零散的結果集
3)可移植: 可移植,可以在java,ruby,#c平臺上使用
缺點:
1)只能在關係型數據庫上使用
2)sql需要程序員編寫。如果數據庫設計改變,需要改ibatis的配置文件,有點麻煩。
3.實例講解ibatis
首先配置ibatis的jar包(兩個,我使用的是ibatis-2.3.4.726.jar和mysql-connector-java-5.0.4-bin.jar)
工程文件如圖:
java文件 :
User: POJO,是持久層對象,也是ibatis直接操作的對象
UserDAO :把參數(User)傳到給User.xml上 。
配置文件包括
JDBC連接的屬性文件:sqlMap.properties.
ibatis總配置文件sqlMapConfig.xml
每個實體的映射文件,這裏是User類的映射文件。 User.xml 在這裏由程序員手動編寫sql語句
sqlMap.properties 中定義了數據庫的連接:
資源文件即key 和value的鍵值對
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/tt
username=root
password=
總配置文件: 注意--我在總配置文件中直接加入了JDBC數據源,並沒有用到工程中的sqlMap.properties。
<?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>
<!-- 定義了ibatis的事務管理器有3中(JDBC,JTA,EXTERNAL) -->
<transactionManager type="JDBC" commitRequired="false">
<!--type屬性指定了數據源的鏈接類型,也有3種類型(SIMPLE,DBCP,JNDI)-->
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/>
<property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost:3306/tt"/>
<property name="JDBC.Username" value="root"/>
<property name="JDBC.Password" value=""/>
</dataSource>
</transactionManager>
<!--配置映射文件-->
<sqlMap resource="com/tt/User.xml"/>
</sqlMapConfig>
解釋:
關於ibatis的事務管理器和數據源 :http://blog.csdn.net/not_a_baby/article/details/6756943、
如果引用sqlMap.properties,即以下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<properties resource="com/tt/sqlMap.properties" />
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="${driver}" />
<property name="JDBC.ConnectionURL" value="${url}" />
<property name="JDBC.Username" value="${username}" />
<property name="JDBC.Password" value="${password}" />
</dataSource>
</transactionManager>
<sqlMap resource="com/tt/User.xml"/>
</sqlMapConfig>
User的映射文件:【對user的增刪改查我只實現了增和改作爲示例】
以下就是經常能看到的sqlMap.xml的實例~這部分的代碼編寫佔據ibatis開發的70%左右。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap>
<select id="selectUser" parameterClass="int" resultClass="com.tt.User">
</select>
<insert id="insertUser" parameterClass="com.tt.User">
<![CDATA[
insert into user (name, age,sex, location)
values (
#name:VARCHAR#,
#age:INT#,
#sex:VARCHAR#,
#location:VARCHAR#
)]]>
<selectKey resultClass="int" keyProperty="id">
SELECT
LAST_INSERT_ID() AS ID
</selectKey>
</insert>
<delete id="deleteUser" parameterClass="int">
</delete>
<select id="selectUsers" parameterClass="com.tt.User">
</select>
<update id="updateUser" parameterClass="com.tt.User">
update user
<dynamic prepend="set">
<isNotNull prepend="," property="name">
name = #name:VARCHAR#
</isNotNull>
<isNotNull prepend="," property="sex">
sex = #sex:VARCHAR#
</isNotNull>
<isNotNull prepend="," property="location">
location = #location:VARCHAR#
</isNotNull>
<isNotNull prepend="," property="age">
age = #age#
</isNotNull>
</dynamic>
where id = #id#
</update>
</sqlMap>
解釋:
ibatis映射 :
1) 關於主鍵:
ibatis支持數據庫逐漸的自動生成,包括與預生成主鍵(插入數據之前就知道哪個是主鍵 eg:oracle)和 後生成主鍵(插入數據之後知道誰是主鍵, eg:mysql)
生成的主鍵會設置到同名屬性中 -----keyProperty屬性指定主鍵屬性
selectKey的位置表示 是預生成主鍵 還是 後生成主鍵
2)對於sql語句中包含> 或者 <號的情況(where條件中可能會有),使用<![CDATA[*********]]> 來包含。*******表示被包含的sql語句,也可以只包含一個> 或者<符號
3)sql的輸入參數parameterClass
插入語句入參: parameterClass = ‘包.類’
查詢語句入參:可以設爲類名,map,或者string,int ,long 等。 只有一個原聲類型(string,int,long)作爲入參是,可以使用#value#來引用。
例如:
<select id ="selectUser" parameterClass ='long' resultClass = 'com.tt.User'> select * from User where id = #value# </select>
我的例子中,沒有id。以上是用法示例、
4)返回值參數類型
resultClass = 'com.tt.User' -當結果集列名和類屬性名完全對應的時候,使用resultClass
resultMap = 'xxx'; ---當有些列不對應的時候。 resultMap 是一個POJO的映射,需要先定義xml的映射,才能被使用。
例如:
<resultMap id="mapUser" class="com.tt.mapUser"> <result property="name" column="name"/> <result property="age" column="age"/> </resultMap>則需要在com.tt包下建立一個POJO類對應,屬性成員爲name, age 。 只表示想知道的列
5)sql中參數的引用
引用parameterClass有三種方式 :
1. 原生類型 -- int , string , long ---使用#value# #value#不是關鍵字,可變
2. map類型參數,使用#keyName#來引用,keyName爲健名
3.對象參數, 使用#propertyName# 使用對象的屬性的名字。 比如上面的name =#name# 等。
6)模糊查詢中參數的引用
瞭解## 和$$ 的區別。
#xxxx#是把 xxxx作爲一個參數傳入
$xxxx$是把xxxx整體直接拼接到sql語句上
在模糊查詢是,要----》 ‘%$Name$%’
7)動態sql --ibatis的亮點
prepend表示鏈接關鍵字,可以爲任何字串,當爲sql關鍵字是,ibatis子歐諾個判斷是否添加該關鍵字。
8)結果集映射繼承
繼承是爲了映射定義的複用。
例如
<resultMap id="baseUser" class="com.tt.User"> <result property="name" column="name"/> <result property="age" column="age"/> </resultMap> <resultMap id="User2" class="com.tt.User" extends="com.tt.User.baseUser"> <result property="sex" column = "sex"/> </resultMap>
9)ibatis的分頁查詢 ---【待完善】
10)sql注入 ---【待完善】
11)ibatis可以配置緩存
12)ibatis各種id的命名
DAO層中接口名字SQL語句id的名字保持一致,
User.java --注意屬性名要與User.xml文件中的屬性相對應、
package com.tt;
/**對象模型
*
* @author taoyutong.pt
*
*/
public class User {
private int id;
private String name;
private int age;
private String sex;
private String location;
public void setLocation(String location) {
this.location = location;
}
public String getLocation() {
return location;
}
public void setGender(String gender) {
this.sex = gender;
}
public String getGender() {
return sex;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
UserDAO 接口:
package com.tt;
import java.sql.SQLException;
import java.util.List;
/**
* UserDAO
* @author taoyutong.pt
*
*/
public interface UserDAO {
//增
public int insertUser(User user)throws SQLException;
//刪
public int deleteUser(int id)throws SQLException;
//改
public int updateUser(User user)throws SQLException;
//查
public User queryUser(int id) throws SQLException;
public List<User> queryUserByDynamic(User user)throws SQLException;
}
UserDAOImpl 實現類:
package com.tt;
/**
* UserDAO實現類
*/
import java.io.IOException;
import java.io.Reader;
import java.sql.SQLException;
import java.util.List;
import com.ibatis.sqlmap.client.SqlMapClient;
public class UserDAOImpl implements UserDAO{
//sqlMapClient
private static SqlMapClient sqlMapClient =null;
static {
try {
Reader reader = com.ibatis.common.resources.Resources
.getResourceAsReader("com/tt/sqlMapConfig.xml");
sqlMapClient = com.ibatis.sqlmap.client.SqlMapClientBuilder
.buildSqlMapClient(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public int insertUser(User user)throws SQLException{
return (Integer)sqlMapClient.insert("insertUser",user);
}
@Override
public int deleteUser(int id)throws SQLException{
return (Integer)sqlMapClient.delete("deleteUser" ,id);
}
@Override
public int updateUser(User user)throws SQLException{
return sqlMapClient.update("updateUser",user);
}
@Override
public User queryUser(int id) throws SQLException{
return (User)sqlMapClient.queryForObject("selectUser",id);
}
@Override
public List<User> queryUserByDynamic(User user)throws SQLException{
return sqlMapClient.queryForList("selectUsers",user);
}
}
AppMain.java 測試
package com.tt;
import java.sql.SQLException;
public class AppMain {
public static void main(String args[]) throws SQLException{
UserDAO userDAO = new UserDAOImpl();
User user =new User();
user.setAge(22);
user.setGender("man");
user.setLocation("dalian");
user.setName("bulu");
System.out.println(userDAO.insertUser(user));//返回自增ID
user.setName("tt");
System.out.println(userDAO.updateUser(user));//
}
}