Mybatis 框架(二)—— Mapper 接口開發規範、映射文件的配置(1)

一、使用 Mybatis 實現增刪改查

1、Mapper 接口開發規範

(1)Mapper.xml 文件中的 namespace 與 mapper 接口的類路徑相同。

  • Mapper接口方法名和Mapper.xml中定義的每個statement的id相同
  • Mapper接口方法的參數類型和mapper.xml中定義的每個sql 的parameterType的類型相同
  • Mapper接口方法的返回值類型和mapper.xml中定義的每個sql的resultType的類型相同

(2)在執行某些數據庫操作時,在sql語句中需要動態的賦予參數,參數的來源是數據層接口中方法的參數,在映射文件中使用這些參數有兩種寫法#{}${}

  • #{}表示一個佔位符號,通過#{}可以實現 preparedStatement 向佔位符中設置值,自動進行 java 類型和 jdbc 類型轉換,#{}可以有效防止 sql 注入。 #{}可以接收簡單類型值或 pojo 屬性值。如果 parameterType 傳輸單個簡單類型值,#{}括號中可以是 value 或其它名稱。
  • ${}表示拼接sql串,通過${}可以將 parameterType 傳入的內容拼接在 sql 中且不進行 jdbc 類型轉換,${}可以接收簡單類型值或 pojo 屬性值,如果 parameterType 傳輸單個簡單類型值,${}括號中只能是value。
    基本上能使用#{}就不要使用${}避免 sql 注入

二、映射文件的配置(1)

1、新增數據時獲取主鍵值

在某些場景中,我們需要使用新增的這一行數據的主鍵值,例如:在新增訂單的操作中,我們首先需要新增一行訂單表數據,然後再新增訂單詳情數據,而訂單詳情中有一個字段用來記錄訂單詳情所屬的訂單編號,這種情況下我們必須獲取到訂單數據的主鍵值,在 jdbc 中我們可以通過 getGeneratedKey 這個函數來獲取新增的主鍵值數據,那麼在 mybatis 中該如何處理呢?
在映射文件的insert標籤和update標籤中可以使用兩個屬性 useGeneratedKeys 和 keyProperty 來完成這個工作。

	<!-- 新增 -->
<insert id="save" parameterType="Products" useGeneratedKeys="true" keyProperty="p_id">
	insert into products(p_name,p_price,p_count) values(#{p_name},#{p_price},#{p_count})
</insert>
  • useGeneratedKeys 設置爲 true 表示當前數據庫使用自增長的方式生成主鍵值,在操作完畢以後會使用該自增長的值
  • keyProperty 則表示在新增完畢以後生成的主鍵值保存在參數的那個屬性中,比如說id屬性
    最後執行新增以後就可以從新增的用戶對象中取出id的值
Products products = new Products();
products.setP_name("M416");
products.setP_price(100);
products.setP_count(20);
mapper.save(products);
session.commit();
//返回新增數據的主鍵值
int keyId = products.getP_id()
System.out.println(keyID);

2、打印sql語句執行過程

使用 mybatis 的日誌,可以打印sql語句的執行過程,只需要在覈心配置文件中添加標籤

<settings>
      <setting name="logImpl" value="STDOUT_LOGGING" /> 
</settings>

3、在mybatis核心配置文件中指定類型的別名

在映射文件中的標籤中經常需要用到類型的名稱,例如 parameterType 和 resultType,雖然直接寫類型的全限定名稱完全可以,但是類的限定名稱往往特別複雜,寫起來非常麻煩,mybatis 同時還支持以別名的方式來定義參數類型或者返回值類型。對於java中的常見類型mybatis已經爲其提供了對應的別名,見下表

別名 映射的類型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
map Map

如果想爲項目中的自定義實體類型定義別名就需要在mybatis的核心配置文件的根標籤中使用typeAliases標籤。

<typeAliases>
	<!-- 定義單個的別名 -->
	<typeAlias type="com.woniu.entity.User" alias="User"/>
	<!-- 批量定義別名:將自動以該包中的所有類的類名作爲別名,不區分大小寫 -->
	<package name="com.woniu.entity"/>
</typeAliases>

在覈心配置文件中注意標籤的書寫位置:

順序 標籤
1 properties
2 settings
3 typeAliases
4 typeHandlers
5 objectFactory
6 objectWrapperFactory
7 reflectorFactory
8 plugins
9 environments
10 databaseIdProvider
11 mappers

4、使用 sql 標籤定義可重用的 sql 語句

在映射文件中使用 sql 標籤定義 sql 語句片段,在需要使用該sql語句片段的標籤中使用 include 標籤引入定義好的 sql 語句。

<sql id="columns">p_id,p_name,p_price</sql>
<select id="select" resultType="Products>
	<include refid="columns"></include>
</select>

5、使用 foreach 標籤實現多行新增

某些數據庫是支持多行新增的,例如 mysql,mysql 中多行新增的語法是:

insert  into 表 values(第一行的數據),(第二行的數據),....以此類推

根據語法結構我們不難發現,要實現多行新增需要在values後重復書寫每一行的數據內容,mybatis 提供了 foreach 標籤可以在執行新增時根據參數,循環拼接sql語句,以此我們可以實現多行新增。
(1)多行新增的參數應該定義爲集合類型

public void insertMore(List<Products> list);

(2)映射文件中的標籤寫法:

<!-- 多行新增 -->
<insert id="insertMore" parameterType="list">
	insert into products values
	<foreach collection="list" item="products" separator=",">
		(null,#{products.p_name},#{products.p_price},#{products.p_count})
	</foreach>
</insert>

foreach 標籤屬性說明:

  • collection:需要循環的集合名稱,必須寫作 list 或者 collection,如果參數類型是Set集合,則必須寫作collection。
  • item:foreach循環時的對象名稱,可以使用該名稱獲取每一個對象中的屬性值。
  • separator:分隔符,每循環一次在末尾自動添加的分隔符(除了最後一次循環)。

6、動態 sql 查詢

動態 sql 主要用於動態的添加查詢條件,動態添加查詢條件可以使用 if 標籤和 where 標籤,用法如下:
(1)單獨使用 if 標籤:

<!-- if標籤 -->
<select id="selectIf" resultType="Products" >
	select
	<include refid="columns"></include>
	from products
	<if test="p_name != null and '' != p_name">
		and p_name = #{p_name}
	</if>
</select>

單獨使用 if 標籤時,test 屬性中書寫條件,可以直接使用參數中的屬性名稱參與判斷,如果條件成立則會拼接if標籤中的 sql 語句,否則不會,在一個 select 中可以使用多個 if 標籤來動態添加多個條件。

(2)where 標籤和 if 標籤配合
where 標籤只會在至少有一個子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句。而且,若語句的開頭爲“AND”或“OR”,where 元素也會將它們去除。

<!-- 動態sql查詢使用where和if標籤 -->
<select id="selectWhere" resultType="Products" parameterType="Products">
       select <include refid="columns"></include> from products
       <where>
        <if test="p_name != null and '' != p_name">
            and p_name = #{p_name}
        </if>
       </where>
</select>

三 、Mybatis 示例 Demo1

(1)實體類
① 商品實體類

public class Products {
	private int p_id;
	private String p_name;
	private double p_price;
	private int p_count;
	private String p_class;
	private String p_attribute;
	private int p_typeid;
	//省略set、get、toString方法
}

② 動態追加條件實體類

public class ProductsExample {
	private List<String> examples = new ArrayList<String>();
	
	public List<String> getExamples() {
		return examples;
	}
	public void setExamples(List<String> examples) {
		this.examples = examples;
	}
	public void eq(String name, Object value) {
		String example = " and " + name + "=" +"'"+value+"'";
		System.out.println(example);
		examples.add(example);
	}
	public void gt(String name, Object value) {
		String example = " and " + name + ">"+value;
		System.out.println(example);
		examples.add(example);
	}
}

(2)數據層 Mapper 層
① 數據層的 SelectMapper 類,定義各類方法

public interface SelectMapper {
	//查詢所有數據
	public List<Products> select();
	//新增數據
	public void save(Products products);
	//刪除數據
	public void delete(Products products);
	//修改數據
	public void update(Products products);
	//模糊查詢數據
	public List<Products> selectLike(String p_name);
	//分頁查詢數據
	public List<Products> selectLimit(Map<String, Object> map);
	//聚合函數count查詢
	public int selectCount();
	//多表聯合查詢
	public List<Products> selectUnion();
	//多行新增
	public void insertMore(List<Products> list);
	//使用if標籤動態sql查詢
	public List<Products> selectIf(Products products);
	//foreach標籤定義查詢多個條件
	public List<Products> selectExample(List<String> list);
	//根據單個字符串數據動態追加條件進行排序
	public List<Products> order(String column);
	//使用where和if標籤動態sql查詢
	public List<Products> selectWhere(Products products);
}

② 數據層與 SelectMapper 類對應的 SelectMapper.xml 文件

<?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">
  
<mapper namespace="com.mybatis.demo1.dao.SelectMapper">
   <!-- sql標籤定義可重用的sql語句 -->
   <sql id="columns">p_id,p_name,p_price,p_count,p_class,p_attribute</sql>
   
   <!-- 查詢所有 -->
   <select id="select" resultType="Products" >
       select <include refid="columns"></include> from products
   </select>
   <!-- 模糊查詢 -->
   <select id="selectLike" resultType="Products" parameterType="string">
       select <include refid="columns"></include> from products where p_name like #{p_name}
   </select>
   <!-- 分頁查詢 -->
   <select id="selectLimit" resultType="Products" parameterType="map">
       select <include refid="columns"></include> from products limit #{startIndex}, #{selectNum}
   </select>
   <!-- 多表聯合查詢 -->
   <select id="selectUnion" resultType="map">
       select p_name,p_price,p_count,lt_name as tname from products as p inner join ltype as t on p.p_typeid = t.lt_id
   </select>
   <!-- 聚合函數count查詢 -->
   <select id="selectCount" resultType="int">
       select count(p_id) from products
   </select>
 
   <!-- 新增 -->
   <insert id="save" parameterType="Products">
       insert into products values(null,#{p_name},#{p_price},#{p_count},#{p_class},#{p_attribute},#{p_typeid})
   </insert>
   <!-- 刪除 -->
   <insert id="delete" parameterType="Products" >
       delete from products where p_id = #{p_id}
   </insert>
   <!-- 修改 -->
   <insert id="update" parameterType="Products" >
       update products set p_price = #{p_price}, p_count = ${p_count} where p_id = ${p_id}
   </insert>
   
   <!-- 多行新增 -->
   <insert id="insertMore" parameterType="list">
        insert into products values
        <foreach collection="list" item="products" separator=",">
            (null,#{products.p_name},#{products.p_price},#{products.p_count},#{products.p_class},#{products.p_attribute},#{products.p_typeid})
        </foreach>
   </insert>
   
   <select id="selectExample" resultType="products" parameterType="list">
        select <include refid="columns"></include> from products where 1 = 1
        <foreach collection="list" item="example">
            ${example}
        </foreach>
   </select>
   
   <!-- 動態sql查詢使用if標籤 -->
   <select id="selectIf" resultType="Products" parameterType="Products">
        select <include refid="columns"></include> from products where 1 = 1
        <if test="p_name != null and '' != p_name">
            and p_name = #{p_name}
        </if>
        <if test="p_price != 0">
            and p_price > #{p_price}
        </if>
        <if test="p_count != 0">
            and p_count > #{p_count}
        </if>
   </select>
   
   <!-- 根據單個字符串數據動態追加條件 -->
   <select id="order" resultType="Products" parameterType="string">
        select <include refid="columns"></include> from products
        <if test="_parameter != null">
            order by ${_parameter}
        </if>
   </select>
   
   <!-- 動態sql查詢使用where和if標籤 -->
   <select id="selectWhere" resultType="Products" parameterType="Products">
        select <include refid="columns"></include> from products
        <where>
	        <if test="p_name != null and '' != p_name">
	            and p_name = #{p_name}
	        </if>
	        <if test="p_price != 0">
	            and p_price > #{p_price}
	        </if>
	        <if test="p_count != 0">
	            and p_count > #{p_count}
	        </if>
        </where>
   </select>
</mapper>

(3)Test 類

public class Test {
	public static void main(String[] args) {
		try {
			//加載配置文件獲取輸入流對象
			InputStream is = Resources.getResourceAsStream("Mybatis1.xml");
			//通過輸入流對象中的信息獲取SqlSessionFactory
			SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
			//通過SqlSessionFactory獲取SqlSession對象
			SqlSession session = factory.openSession();
			
			SelectMapper mapper = session.getMapper(SelectMapper.class);
			//新增數據
			Products products = new Products();
			products.setP_name("M416");
			products.setP_price(100);
			products.setP_count(20);
			products.setP_class("武器");
			products.setP_attribute("突擊步槍");
			products.setP_typeid(1);
			mapper.save(products);
			session.commit();
			//返回新增數據的主鍵值
			System.out.println(products.getP_id());
			
			//刪除數據
			Products products = new Products();
			products.setP_id(213);
			mapper.delete(products);
			session.commit();
			
			//修改數據
			Products products = new Products();
			products.setP_id(213);
			products.setP_price(111);
			products.setP_count(234);
			mapper.update(products);
			session.commit();
			
			//查詢所有數據
			List<Products> list = mapper.select();
			System.out.println(list);
			
			//分頁查詢數據
			int startIndex = 5;	//設置起始查詢頁
			int selectNum = 10;	//設置每頁顯示數量
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("startIndex", (startIndex - 1) * selectNum);
			map.put("selectNum", selectNum);
			List<Products> list = mapper.selectLimit(map);
			System.out.println(list);
			
			//模糊查詢數據
			String p_name = "%M%";
			List<Products> list = mapper.selectLike(p_name);
			System.out.println(list);
			
			//多表聯合查詢
			List<Products> list = mapper.selectUnion();
			session.commit();
			System.out.println(list);
			
			//聚合函數count查詢
			int count = mapper.selectCount();
			session.commit();
			System.out.println(count);
			
			//多行新增
			List<Products> list = new ArrayList<Products>();
			Products products1 = new Products();
			products1.setP_name("M416");
			products1.setP_price(100);
			products1.setP_count(20);
			products1.setP_class("武器");
			products1.setP_attribute("突擊步槍");
			products1.setP_typeid(1);
			
			Products products2 = new Products();
			products2.setP_name("M416");
			products2.setP_price(100);
			products2.setP_count(20);
			products2.setP_class("武器");
			products2.setP_attribute("突擊步槍");
			products2.setP_typeid(1);
			list.add(products1);
			list.add(products2);
			mapper.insertMore(list);
			session.commit();
			
			//foreach標籤定義查詢多個條件
			ProductsExample example = new ProductsExample();
			example.eq("p_name", "M416");
			example.gt("p_price", "1000");
			List<Products> list = mapper.selectExample(example.getExamples());
			System.out.println(list);
			
			//使用if標籤動態sql查詢
			Products products = new Products();
			products.setP_name("M416");
			products.setP_price(1000);
			products.setP_count(100);
			List<Products> list = mapper.selectIf(products);
			System.out.println(list);
			
			//根據單個字符串數據動態追加條件進行排序
			List<Products> list = mapper.order("p_price");
			System.out.println(list);
			
			//使用where和if標籤動態sql查詢
			Products products = new Products();
			products.setP_name("M416");
			products.setP_price(1000);
			products.setP_count(100);
			List<Products> list = mapper.selectWhere(products);
			System.out.println(list);
			
			session.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章