1. 程式人生 > >MyBatis的sql對映檔案(CRUD和主鍵id生成)

MyBatis的sql對映檔案(CRUD和主鍵id生成)

一個好的講解mybatis的部落格地址http://www.jianshu.com/nb/5226994

官方文件:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

Mapper XML 檔案

MyBatis 的真正強大在於它的對映語句,也是它的魔力所在。由於它的異常強大,對映器的 XML 檔案就顯得相對簡單。如果拿它跟具有相同功能的 JDBC 程式碼進行對比,你會立即發現省掉了將近 95% 的程式碼。MyBatis 就是針對 SQL 構建的,並且比普通的方法做的更好。

SQL 對映檔案有很少的幾個頂級元素(按照它們應該被定義的順序):

  • cache – 給定名稱空間的快取配置。
  • cache-ref – 其他名稱空間快取配置的引用。
  • resultMap – 是最複雜也是最強大的元素,用來描述如何從資料庫結果集中來載入物件。
  • parameterMap – 已廢棄!老式風格的引數對映。內聯引數是首選,這個元素可能在將來被移除,這裡不會記錄。
  • sql – 可被其他語句引用的可重用語句塊。
  • insert – 對映插入語句
  • update – 對映更新語句
  • delete – 對映刪除語句
  • select – 對映查詢語句

 

全域性對映檔案

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 1. 匯入資原始檔 -->
	<properties resource="application.properties"></properties>
	<settings>
		<!-- 開啟自動駝峰命名規則對映,即從經典資料庫列名 A_COLUMN 到POJO類屬性名 aColumn的類似對映。 -->
		<setting name="mapUnderscoreToCamelCase" value="true"/>
	</settings>	

 	<!-- 2. 配置資料庫的連線環境(default為id的值),即預設載入的資料庫環境	 -->
	<environments default="mysql">
		<environment id="mysql"> 				<!-- 配置具體的資料庫環境    id唯一	 -->
			<transactionManager type="JDBC" />  <!-- 指定使用的事務處理管理器 -->
			<dataSource type="POOLED">  		<!-- 指定使用的資料來源連線池		 -->
				<property name="driver" value="${jdbc.driverClass}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.user}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
		<environment id="oracle"> 				
			<transactionManager type="JDBC" />  
			<dataSource type="POOLED">  		
				<property name="driver" value="${oracle.driverClass}" />
				<property name="url" value="${oracle.url}" />
				<property name="username" value="${oracle.user}" />
				<property name="password" value="${oracle.password}" />
			</dataSource>
		</environment>
	</environments>
	
	<!-- 3. 引入mapper對映檔案 -->
	<mappers>
		<package name="cn.jq.mybatis.dao" /> 
	</mappers>
</configuration>

application.properties 檔案

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_demo?useUnicode=true&characterEncoding=utf8&useSSL=true
jdbc.user=root
jdbc.password=123456

oracle.driverClass=oracle.jdbc.OracleDriver
oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
oracle.user=scott
oracle.password=tiger

一、簡單增刪改查操作

1、 對映介面實現類

public interface UserMapper {
	/**
	 * 
	 * 根據id查詢一條記錄
	 * @param id
	 * @return
	 */
	//@Select("select * from t_user where id = #{id}")
	public User getUser(Integer id);

	/**
	 * 查詢資料庫中的記錄總條數
	 * @return
	 */
	public int selectCount();

	/**
	 * 新增一條記錄
	 * @param user
	 * @return 資料庫受影響的行數
	 */
	public int insertUser(User user);

	/**
	 * 刪除一條記錄
	 * @param id
	 * @return 資料庫受影響的行數
	 */
	public int deleteUser(Integer id);
	
	/**
	 * 修改一條記錄
	 * @param user
	 * @return 資料庫受影響的行數>=1 返回true 否則返回false
	 */
	public boolean updateUser(User user);
	
	/**
	 * 查詢所有記錄
	 * @return List<User>
	 */
	public List<User> selectUserAll();
}

2、sql對映檔案

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- namespace - 名稱空間對應對映介面的全限定名 -->
<mapper namespace="cn.jq.mybatis.dao.UserMapper">
	<!-- id - 對應介面中的方法名
	     resultType - 從這條語句中返回的期望型別的類完全限定名或別名 
	     parameterType - 傳入這條語句的引數類的完全限定名或別名  -->
	<select id="getUser" resultType="cn.jq.mybatis.model.User">
		select * from t_user where id = #{id}
	</select>

	<select id="selectCount" resultType="int">
		select count(*) from t_user
	</select>
	
	<insert id="insertUser" parameterType="cn.jq.mybatis.model.User">
		insert into t_user(username,pazzword,state,reg_date) values(#{username},#{pazzword},#{state},#{regDate})
	</insert>
	
	<delete id="deleteUser" parameterType="int">
		delete from t_user where id=#{id}
	</delete>
	
	<update id="updateUser" parameterType="cn.jq.mybatis.model.User">
		update t_user set username=#{username},pazzword=#{pazzword},state=#{state},reg_date=#{regDate} where id=#{id}
	</update>
	
	<!--  返回型別為集合時,resultType只需指定List中單行記錄的型別即可
	     resultType - 從這條語句中返回的期望型別的類完全限定名或別名 -->
	<select id="selectUserAll" resultType="cn.jq.mybatis.model.User">
		select * from t_user
	</select>	
</mapper>

3、測試類

	@Test
	public void test() throws IOException {
		//1. 建立SqlSessionFacotry工廠類物件,根據讀取全域性配置檔案
		Resources.setCharset(Charset.forName("utf-8"));//設定編碼格式
		InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		//2. 開啟資料庫連線會話
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
			//3.通過會話操作sql 返回的是代理物件 jdk動態代理
			UserMapper userMapper = session.getMapper(UserMapper.class);
			
			//查詢一條記錄
			User user = userMapper.getUser(2);
			//查詢資料庫中的記錄總條數
			int  count = userMapper.selectCount();
			//查詢所有記錄
			List<User> userlist = userMapper.selectUserAll();
			System.out.println(count);
			System.out.println(user);
			System.out.println(Arrays.asList(userlist));
			
			//新增一條記錄
			User user2 = new User("李四", "123456", 1, new Date());
			int i = userMapper.insertUser(user2);
		        System.out.println("成功新增"+i+"條資料");
			session.commit(); //提交事務
			
			//修改一條記錄
			User user3 = new User();
			user3.setId(3);
			user3.setUsername("li33");
			user3.setPazzword("li33qq");
			user3.setState(0);
			user3.setRegDate(new Date());
			boolean b = userMapper.updateUser(user3);
			session.commit();
			System.out.println("成功修改"+b+"條資料");
			
			//刪除一條記錄
			int n = userMapper.deleteUser(13);
			session.commit();
			System.out.println("成功刪除"+n+"條資料");
			
			System.out.println(userMapper.selectCount());
			
		} finally {
			//關閉會話
			session.close();
		}						
	}
----
3
User [id=2, username=user, pazzword=3be7f713d9321e812231bb838448385d, state=1, regDate=Mon Oct 15 00:00:00 CST 2018]
[[User [id=1, username=admin, pazzword=172eee54aa664e9dd0536b063796e54e, state=1, regDate=Sun Oct 14 00:00:00 CST 2018], User [id=2, username=user, pazzword=3be7f713d9321e812231bb838448385d, state=1, regDate=Mon Oct 15 00:00:00 CST 2018], User [id=3, username=阿斯達, pazzword=d0dbbe3c3b4d61ef587448bbdc103de7, state=1, regDate=Tue Oct 23 00:00:00 CST 2018]]]
成功新增1條資料
成功修改true條資料
成功刪除1條資料
4

   

注意:CRUD是可以直接設定返回值的,int, long, boolean 和 void 都可以是返回值型別,int 和long返回影響資料庫條數,boolean影響的條數大於1返回true,否則返回false.

標籤屬性:

屬性 描述
id 在名稱空間中唯一的識別符號,可以被用來引用這條語句。
parameterType 將會傳入這條語句的引數類的完全限定名或別名。這個屬性是可選的,因為 MyBatis 可以通過 TypeHandler 推斷出具體傳入語句的引數,預設值為 unset。
parameterMap 這是引用外部 parameterMap 的已經被廢棄的方法。使用內聯引數對映和 parameterType 屬性。
resultType 從這條語句中返回的期望型別的類的完全限定名或別名。注意如果是集合情形,那應該是集合可以包含的型別,而不能是集合本身。使用 resultType 或 resultMap,但不能同時使用。
resultMap 外部 resultMap 的命名引用。結果集的對映是 MyBatis 最強大的特性,對其有一個很好的理解的話,許多複雜對映的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同時使用。
flushCache 將其設定為 true,任何時候只要語句被呼叫,都會導致本地快取和二級快取都會被清空,預設值:false。
useCache 將其設定為 true,將會導致本條語句的結果被二級快取,預設值:對 select 元素為 true。
timeout 這個設定是在丟擲異常之前,驅動程式等待資料庫返回請求結果的秒數。預設值為 unset(依賴驅動)。
fetchSize 這是嘗試影響驅動程式每次批量返回的結果行數和這個設定值相等。預設值為 unset(依賴驅動)。
statementType STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,預設值:PREPARED。
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一個,預設值為 unset (依賴驅動)。
databaseId 如果配置了 databaseIdProvider,MyBatis 會載入所有的不帶 databaseId 或匹配當前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。
resultOrdered 這個設定僅針對巢狀結果 select 語句適用:如果為 true,就是假設包含了巢狀結果集或是分組了,這樣的話當返回一個主結果行的時候,就不會發生有對前面結果集的引用的情況。這就使得在獲取巢狀的結果集的時候不至於導致記憶體不夠用。預設值:false。
resultSets 這個設定僅對多結果集的情況適用,它將列出語句執行後返回的結果集並每個結果集給一個名稱,名稱是逗號分隔的。
useGeneratedKeys (僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由資料庫內部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關係資料庫管理系統的自動遞增欄位),預設值:false。
keyProperty (僅對 insert 和 update 有用)唯一標記一個屬性,MyBatis 會通過 getGeneratedKeys 的返回值或者通過 insert 語句的 selectKey 子元素設定它的鍵值,預設:unset。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。
keyColumn (僅對 insert 和 update 有用)通過生成的鍵值設定表中的列名,這個設定僅在某些資料庫(像 PostgreSQL)是必須的,當主鍵列不是表中的第一列的時候需要設定。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。
order 這可以被設定為 BEFORE 或 AFTER。如果設定為 BEFORE,那麼它會首先選擇主鍵,設定 keyProperty 然後執行插入語句。如果設定為 AFTER,那麼先執行插入語句,然後是 selectKey 元素 - 這和像 Oracle 的資料庫相似,在插入語句內部可能有嵌入索引呼叫。

 

二、獲取新增記錄生成主鍵id值

1、Mysql生成主鍵id

       資料庫支援自動生成主鍵的欄位(比如 MySQL 和 SQL Server),設定 useGeneratedKeys=”true”,然後再把 keyProperty 設定到目標屬性上就OK。

	 <!-- mysql資料庫 :資料庫本身有自動生成主鍵的方式
  	         useGeneratedKeys - true 設定使用資料庫本身的功能設定主鍵
  	         keyProperty - 設定在model物件中主鍵列對應的屬性名稱(結果自動存放在該屬性中) 區分大小寫的  -->
	<insert id="insertUser" parameterType="cn.jq.mybatis.model.User" useGeneratedKeys="true" keyProperty="id" databaseId="mysql">
		insert into t_user
			(username,pazzword,state,reg_date) 
		values
			(#{username},#{pazzword},#{state},#{regDate})
	</insert>

提交事務之前可以獲取到自動生成id主鍵的值,若不設定獲取不到

			//新增一條記錄
			User user2 = new User("李四", "123456", 1, new Date());
			int i = userMapper.insertUser(user2);
			System.out.println("成功新增"+i+"條資料" + user2.getId()); //成功新增1條資料16
			session.commit(); //提交事務

2、oracle 使用序列生成主鍵id

       對於不支援自動生成型別的資料庫或可能不支援自動生成主鍵的 JDBC 驅動, 如oracle 使用序列

  1)建表 和 建序列

CREATE TABLE t_user (
  ID NUMBER NOT NULL,
  username varchar(255) NOT NULL,
  pazzword varchar(255) NOT NULL,
  state NUMBER DEFAULT NULL,
  reg_date DATE DEFAULT NULL,
  PRIMARY KEY (ID)
);

CREATE SEQUENCE seq_userid
		START WITH 1
		INCREMENT BY 1
		MAXVALUE 999999
		NOCYCLE
		NOCACHE ;

  2)sql對映檔案

  注意: 要把全域性對映檔案的連線環境切換為 oracle , 引入 oracle 依賴 

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>12.1.0.1-atlassian-hosted</version>
        </dependency>

<environments default="oracle">
	<insert id="insertUser" parameterType="cn.jq.mybatis.model.User">
		<!-- 1.先將序列中的值查詢出來 存放在model物件中 新增語句中直接使用該model的屬性即可 
  			order - before 該語句在新增語句之前執行
  			keyProperty - 查詢結果存放在model物件中的那個屬性中(insert中直接使用屬性即可)  
  		
  		oracle資料庫中 允許為null的列 引數中可設定jdbcType
  			jdbcType的型別在org.apache.ibatis.type.JdbcType列舉中定義的
  	-->
		<selectKey order="BEFORE" keyProperty="id" resultType="int">
			select seq_userid.nextval id from dual
		</selectKey>
		insert into t_user
			(id,username,pazzword,state,reg_date) 
		values
			(#{id},#{username},#{pazzword},#{state,jdbcType=NUMERIC},#{regDate,jdbcType=DATE})
	</insert>

  3)測試類

			User user2 = new User("李四", "123456", 1, new Date());
			int i = userMapper.insertUser(user2);
			System.out.println("成功新增"+i+"條資料" + user2.getId()); //成功新增1條資料1
			session.commit(); //提交事務