1. 程式人生 > 實用技巧 >【Mybatis】Mybatis實戰1

【Mybatis】Mybatis實戰1

MyBatis 框架

資料持久層框架(DAO將資料持久化到資料庫),實現DAO層的程式碼。對JDBC程式碼的封裝。
特點:
①封裝通用功能,簡化程式碼,提高開發效率(獲得conn,繫結引數,傳送sql,處理異常,處理結果集)
②sql放在配置檔案中,提高sql可維護性。
③自帶連線池功能
④自帶快取(提高查詢效率) [重點]

1).第一個MyBatis程式

核心程式設計思想
①書寫DAO介面
②開發Mapper檔案
   SQL+繫結的引數===實現介面中的方法。
 

環境搭建
1. 匯入jar。
   1. 匯入mybatis的jar
   2. 匯入oracle的驅動jar
   3. 匯入mybatis依賴lib的jar。
2. 引入配置檔案: 
   mybatis-config.xml(連線資料庫相關的引數)
   	driverClassName 			oracle.jdbc.OracleDriver
   	url						jdbc:oracle:thin:@localhost:1521:xe
   	username				hr
   	password					hr
   		transactionManager		連線池(POOLED/UNPOOLED) 			
  XxxMapper.xml(相當於dao的實現類)
3. 初始化配置

2).MyBatis實現DAO、以及重要的API

(1)實現DAO程式設計
① 寫DAO介面
public interface PersonDAO{
	 void insert(Person person);
}
② 書寫Mapper檔案(DAO的實現類)[sql+引數]
<insert id="實現介面的方法名" parameterType="引數中實體型別全類名">
		insert into t_person values(seq_person.nextval,#{屬性名},#{sex},#{age},#{mobile},#{address})
</insert>
屬性:	id: 實現的介面的方法名
parameterType: 引數型別(實體的全類名)  
sql語中繫結引數: #{屬性名}
③ 註冊管理mapper檔案[在mybatis-config中配置]
<mappers>
		<!-- 註冊管理所有的mapper檔案 -->
		<mapper resource="com/baizhi/demo1/PersonDAOImpl.xml"></mapper>
</mappers>
resource: mapper檔案相對於src的路徑。

(2)重要API
目的:
使用DAO獲得PersonDAO的物件、呼叫personDAO的方法。
常用的類:
sqlSession: 
	①獲得dao介面的實現類的物件。
		XxxDAO dao = sqlSession.getMapper(介面.class);
	②相當於connection.[提交事務 關閉close,回滾事務]
SqlSessionFactory
	①獲得sqlSession
		SqlSession session = sqlSessionFactory.openSession();
  ②儲存封裝mybatis-config.xml配置檔案。
    
SqlSessionFactoryBuilder: 讀取配置檔案
Resources: 獲得讀取配置檔案的輸入流。
步驟:
①獲得mybatis-config的輸入流
②讀取mybatis-config的檔案,構造成SqlSessionFactory
③通過SqlSEssionFactory獲得SqlSession
④通過SqlSession獲得DAO介面的物件
⑥呼叫方法測試。

3).MyBatis-DAO介面的修改、刪除、(模糊)查詢、多參方法呼叫

(1)操作
①修改
a. 書寫PersonDAO介面,宣告修改的方法
   public interfafce PersonDAO{
       public void update(Person person);
   }
b. 在Mapper通過標籤實現方法
   <update id="update" parameterType="Person的全類名">
update t_person set name = #{name},sex =#{sex},age=#{age},mobile=#{mobile},address=#{address} where id = #{id}
   </update>
c. 註冊mapper檔案 [一個介面,對應一個mapper檔案,註冊一次]

②刪除
a. 定義dao介面的方法
b. 書寫mapper檔案標籤
 
c. 註冊mapper檔案。
限定引數繫結的名字
a.定義介面方法
   public interface PersonDAO{ public void delete(@Param("指定引數繫結使用的名字")Integer id); }
b Mapper檔案
   <delete>delete from t_person where id = #{指定引數繫結使用的名字} </delete>
③查詢
查詢單個:
a. 書寫DAO介面方法
   public interface PersonDAO{ Person selectById(Integer id); }
b.  mapper檔案實現該方法(sql  引數  對查詢結果對映實體物件)
   <select id="selectById" parameterType="java.lang.Integer" resultType="一行資料對映實體物件型別
   	select id,name,sex,age,mobile,address from t_person where id = #{id}
   </select>
c. 註冊mapper檔案
ResultType的作用:
作用: 對映查詢結果的列封裝成實體的屬性
要求: 查詢結果的列名必須和實體的屬性名一致
注意:表列名和實體屬性名不一致時,通過sql 的as起別名方式,使查詢結果的列名和實體的屬性名一致。
查詢多個:
只需要明確單行資料對映的實體型別,MyBatis會自動講每個資料封裝的每個實體放入list集合中。
a. 書寫DAO介面方法
   	public interface PersonDAO {List<Person> selectAll(); }
b. 書寫mapper檔案中的標籤
   	<select id="selectAll" resultType="rs的一行資料對映實體型別">
   		select id,name,sex,age,mobile,address from t_person
   	</select>
c. 註冊mapper檔案
模糊查詢:
		<select id="selectByName" resultType="rs的一行資料對映實體型別" paramType=”java.lang.String”>
   		select * from t_person where name = ‘%’ || #{name} ||‘%’
			或 select * from t_person where name = ‘%${name}%’
   	</select>
④多個引數(基本,包裝,String):
方案一:
@Param給介面方法的引數起別名
public interface UserDAO {
	User selectByUsernameAndPassword(@Param("username")String username,@Param("password")String password);
}
//可以不用寫型別
select id,username,password from t_user where username = #{username} and password = #{password}
方案二:
繫結引數通過#{引數的序號從0開始}
 注意:MyBatis的Mapper檔案的sql書寫 >或者 <
問題: 會發生轉義
解決: 替換成轉義字元
 
MyBatis注意事項總結:
①增刪改必須要提交事務。(事務自動開啟,手動提交模式)
②引數繫結情況
		實體型別        							#{屬性名}
    	(單個引數)基本資料型別+包裝型別+String		  	#{隨便}
    	沒有引數 									parameterType不用寫
    	多個引數									可以起別名,可以按序號繫結
③mapper檔案轉義字元
	sql的篩選條件: 	<  	 ---> &lt;
				   	>	 ---> &gt;
					&	 ---> &amp;
					“ 	 ---> &quot;
					© 	 ---> &apos;
		eg: select * from t_user where id &lt;= 1000; //選擇id值不超過1000的使用者資訊

4).MyBatisUtil類的封裝、MyBatis的使用技巧、以及日誌

(1)MyBatisUtil類的封裝
MyBatis核心API
SqlSession:
	①相當於connection
		sqlSession.commit();//提交事務
		sqlSession.rollback();//回滾事務
		sqlSession.close();//將連線還回連線池。
	②獲得XXxDAO介面的物件。
		輕量級物件,每次操作建立一個新的。
		比如: Action  SqlSession  Connection
③SqlSessionFactory
		作用: 封裝mybatis-config配置檔案的資訊。
		重量級物件,web應用只建立一個。物件的建立消耗資源。
java程式碼:
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisUtil2 {
	private static SqlSessionFactory factory = null;
	private static ThreadLocal<SqlSession> tdl = new ThreadLocal<SqlSession>();
	static{
		InputStream is = null;
		try {
			is = Resources.getResourceAsStream("mybatis-config.xml");
			factory =  new SqlSessionFactoryBuilder().build(is);
		} catch (IOException e) {throw new RuntimeException("mybatis配置檔案載入異常",e);
		}finally{
			if(is != null){
				try {	is.close();
				} catch (IOException e) {	e.printStackTrace();	}
			}
		}
	}
	/** 獲得SqlSession */
	public static SqlSession getSqlSession(){
		SqlSession session = null; 		//1. 獲得DAO物件  sqlSession
		try {
			session = tdl.get();
			if(session == null){ //當前執行緒如果沒有sqlSEssion
				session = factory.openSession();
				tdl.set(session); 	//將session存入當前執行緒
			}
		} catch (Exception e) {throw new RuntimeException("獲得SqlSession的異常",e);}
		return session;
	}
	/** 根據介面的類物件,獲得dao的物件*/
	public static <T> T getMapper(Class<T> clazz){
		SqlSession session = getSqlSession();	//獲得sqlSession
		T t = session.getMapper(clazz); //呼叫session.getMapper(clazz);
		return t;
	}
	/** 提交事務+釋放資源*/
	public static void commit(){
		//sqlSession.commit();
		try{
			SqlSession session = getSqlSession();
			session.commit();
		}catch(RuntimeException e){throw e;
		}finally{close();}
	}
	/** 回滾事務+釋放資源 */
	public static void rollback(){
		try{
			SqlSession session = getSqlSession();
			session.rollback();
		}catch(RuntimeException e){	throw e;
		}finally{close();}
	}
	/** 釋放session資源 */
	public static void close(){
		//session.close();
		SqlSession session = getSqlSession();
		if(session != null){
			session.close();
			//從當前執行緒中移除該session
			tdl.remove();
		}
	}
}
(2)MyBatis使用技巧、日誌
①配置檔案提示
 
②日誌
MyBatis整合日誌功能:mybatis執行期間的痕跡,通過控制檯列印。
目的: 檢視mybatis執行的痕跡,除錯,驗證。
使用: 匯入日誌的jar log4j.jar; 匯入配置檔案. log4j.properties   [必須放在src根目錄]
補救工作:在建立專案時java version可以選擇高版本、Target Runtime可以選擇自己安裝的TomCat

5).MyBatis實體起別名(簡化)、引數繫結底層原理、物件插入後繫結隨機的id(可返回)

(1)實體簡化
①給實體類的許可權定名取別名。(mybatis-config配置檔案)
   com.baizhi.demo1.Person      別名="Person"
   <typeAliases>
   	<typeAlias type="實體的全類名" alias="別名"></typeAlias>
   	<typeAlias></typeAlias>
   </typeAliases>
②Mapper使用實體類名
	resultType="Person" 或 parameterType=”Person”
(2)引數繫結的底層原理
①預設mapper檔案繫結引數 		#{xxx}
	說明:底層使用的PreparedStatement物件,使用的是SQL預編譯執行、引數繫結。
	優點: 防止sql注入、相對效率高(一點)
    缺點: 只能繫結資料值. sql關鍵字,列 非資料無法繫結。
②使用sql字串拼接繫結引數		${xx}
	優點: 可以繫結任何內容。(關鍵詞,列)
	缺點: sql注入。
	mybatis使用字串拼接繫結引數: ${xx}
(3)插入操作後的實體物件繫結id
	傳統的插入:提前查出要隨機的id:select 序列名.nextval from dual;然後呼叫物件的set方法進行繫結。
	MyBatis方式:
<insert id='insert' parameterType="實體型別">
    <!--在insert語句之前,執行select序列的sql,為了給引數的id屬性繫結值。-->
    <selectKey order="BEFORE"  resultType="型別" keyProperty="sql執行結果繫結引數的實體的屬性名,例如id">
    	select seq_user.nextval from dual
    </selectKey>
	insert into t_user values(#{id},…)
</insert>
	注:order(在插入語句之前繫結),keyProperty(要繫結的屬性名)