1. 程式人生 > >MyBatis教程3【對映檔案和動態sql】

MyBatis教程3【對映檔案和動態sql】

1.logj

在程式的執行的過程中為了便於查詢sql的輸出,需要引入logj新增依賴

<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.25</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.7.25</version>
</dependency>
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

新增log4j.properties檔案

log4j.rootCategory=DEBUG, stdout , R
 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
 
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=C:\\tools\\logs\\dpb.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

效果 在這裡插入圖片描述

2.傳入引數【$和#】

由於MyBatis底層還是Jdbc,而Jdbc在操作資料庫傳遞引數時,有兩種方式,一種是使用Statement,還有一種是使用PreparedStatement: 使用statement時,存在SQL注入問題,PreparedStatement則通過預編譯解決了SQL注入問題。   在MyBatis中,引入引數有兩種方式,一種是使用#,還有一種是使用$,其中,使用#對應了Jdbc種的PreparedStatement,而使用$則對應了Jdbc種的Statement,因此在MyBatis種,推薦使用#。

#的使用

在這裡插入圖片描述 在這裡插入圖片描述

$的使用

加入可以使用$替換#,注意,如果使用$,需要在Mapper種指定引數名字 在這裡插入圖片描述

在這裡插入圖片描述

包裝物件

javabean

public class UserWrapper {

	private User user;

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}
}

對映檔案

<!-- 從包裝物件中獲取資訊 包裝物件的別名. 取資訊 -->
<insert id="addUser4" parameterType="UserWrapper">
	insert into t_user(name,age,favorites)values(#{user.name},#{user.age}
	,#{user.favorites})
</insert>

測試

在這裡插入圖片描述 在這裡插入圖片描述

3.返回資料

ResultType

對於簡單資料型別,例如查詢總記錄數、查詢某一個使用者名稱這一類返回值是一個基本資料型別的,直接寫Java中的基本資料型別即可。   如果返回的是一個物件或者集合,並且物件中的屬性和查詢的欄位名是一一對應的,那麼resultType也可以直接寫一個物件。

ResultMap

resultMap主要用來解決屬性名和欄位名不一致以及一對多、一對一查詢等問題 欄位名不一致時,首先可以通過取別名解決,例如Bean的定義如下:

User物件

private int id;

// 該型別和欄位不一致
private String username;

private int age;

對映檔案

在這裡插入圖片描述 在這裡插入圖片描述

解決方式一:給欄位取別名,這裡講解解決方式二:

<resultMap type="com.sxt.bean.User" id="baseMap">
	<id column="id" property="id"/>
	<result property="username" column="name"/>
	<result property="age" column="age"/>
</resultMap>
 <select id="getUserById" resultMap="baseMap"
 	 resultType="com.sxt.bean.User"> 
	select id ,name ,age  from t_user where id=${id}   
</select> 

在這裡插入圖片描述

主鍵回寫

 一般情況下,主鍵有兩種生成方式:

主鍵自增長
自定義主鍵(一般可以使用UUID)

  如果是第二種,主鍵一般是在Java程式碼中生成,然後傳入資料庫執行,如果是第一個主鍵自增長,此時,Java可能需要知道資料新增成功後的主鍵。 在MyBatis中,可以通過主鍵回填來解決這個問題(推薦)。

主鍵回填

<insert id="add" parameterType="user" useGeneratedKeys="true" keyProperty="id">
	insert into t_user(username,password) values (#{name},#{password})
	</insert>

在這裡插入圖片描述 在這裡插入圖片描述

selectKey

另外,可以利用MySQL自帶的==last_insert_id()==函式查詢剛剛插入的id

<insert id="add1" parameterType="user">
	<selectKey keyProperty="id" resultType="int" >
		select LAST_INSERT_ID()
	</selectKey>
	insert into t_user(username,password) values (#{name},#{password})
	</insert>

在這裡插入圖片描述

動態sql語句

MyBatis 的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其它類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句的痛苦。例如拼接時要確保不能忘記新增必要的空格,還要注意去掉列表最後一個列名的逗號。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。   雖然在以前使用動態 SQL 並非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 對映語句中的強大的動態 SQL 語言得以改進這種情形。   動態 SQL 元素和 JSTL 或基於類似 XML 的文字處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時間瞭解。MyBatis 3 大大精簡了元素種類,現在只需學習原來一半的元素便可。MyBatis 採用功能強大的基於 OGNL 的表示式來淘汰其它大部分元素。

if語句

動態 SQL 通常要做的事情是根據條件包含 where 子句的一部分。比如

<select id="queryUser" resultMap="baseMap"
 	 resultType="com.sxt.bean.User" parameterType="user"> 
	select id ,name ,age  from t_user 
	where 1 =1 
	<if test="username!=null">
	     and name = #{username}
	</if>  
</select> 

// 介面
public List<User> queryUser(User user);

測試 在這裡插入圖片描述

where語句

在使用if語句做動態條件處理的時候如果所有條件都不滿足,那麼得到的SQL語句如下:

select * from t_user where 

在這種情況下,我們一般會加一個1=1來匹配語法規則

	<select id="queryUser" resultMap="baseMap"
	 	 resultType="com.sxt.bean.User" parameterType="user"> 
		select id ,name ,age  from t_user 
		where 1 =1  
		<if test="username!=null">
		     and name = #{username}
		</if>  
	</select> 

此時可以使用標籤來處理這種情況

	<select id="queryUser" resultMap="baseMap"
	 	 resultType="com.sxt.bean.User" parameterType="user"> 
		select id ,name ,age  from t_user 
		<where>
			<if test="username!=null">
			     and name = #{username}
			</if>  
		</where>
	</select> 

在這裡插入圖片描述 在這裡插入圖片描述

set語句

set主要也是用來解決更新問題的。

<update id="updateBookById">
	update t_book
	<set>
			<if test="author!=null"> author=#{author},</if>
			<if test="name!=null"> b_name=#{name},</if>
			<if test="price!=null"> price=#{price},</if>
	</set>
	where id=#{id};
</update>

foreach語句

foreach用來遍歷,遍歷的物件可以是陣列,也可以是集合

dao層介面

在這裡插入圖片描述

mapper對映檔案

<select id="query1" resultType="User" resultMap="basemap">
				select * from t_user
				where id in
				<foreach collection="ids" open="(" close=")" separator="," item="id">
						#{id}
				</foreach>

	</select>
	
	
	<insert id="add2" parameterType="user" useGeneratedKeys="true" keyProperty="id">
	insert into t_user(username,password) values 
	<foreach collection="users" separator="," item="user">
	(#{user.name},#{user.password})
	</foreach>
	</insert>

在這裡插入圖片描述

bind元素

bind 元素可以從 OGNL 表示式中建立一個變數並將其繫結到上下文。

<select id="getUserById" resultMap="baseMap" resultType="com.sxt.bean.User">
	<!-- 聲明瞭一個引數aaa 在後面就可以使用了 -->
	<bind name="aaa" value="12"/>
	select
	id ,name ,age from t_user where id=${aaa}
</select>

在這裡插入圖片描述

sql塊

sql片段一般用來定義sql中的列 在這裡插入圖片描述

關聯關係

在關係型資料庫中,表與表之間很少是獨立與其他表沒關係的。所以在實際開發過程中我們會碰到很多複雜的關聯關係。在此我們來分析下載mybatis中怎麼處理這些關係

1對1

我們有一張員工表(T_EMP),一張部門表(T_DEPT)。員工表中的一條記錄對應於部門表中有且僅有一條記錄。這就是一對一的關聯關係。

查詢每個員工的資訊及對應的部門資訊

部門物件

package com.sxt.bean;

public class Dept {
	private Integer deptid;
	
	private String deptname;
	
	private String deptdesc;

	public Integer getDeptid() {
		return deptid;
	}

	public void setDeptid(Integer deptid) {
		this.deptid = deptid;
	}

	public String getDeptname() {
		return deptname;
	}

	public void setDeptname(String deptname) {
		this.deptname = deptname;
	}

	public String getDeptdesc() {
		return deptdesc;
	}

	public void setDeptdesc(String deptdesc) {
		this.deptdesc = deptdesc;
	}

	@Override
	public String toString() {
		return "Dept [deptid=" + deptid + ", deptname=" + deptname + ", deptdesc=" + deptdesc + "]";
	}
}

員工物件

package com.sxt.bean;

public class Emp {
	private Integer id;
	
	private String name;
	
	private Dept dept;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Dept getDept() {
		return dept;
	}

	public void setDept(Dept dept) {
		this.dept = dept;
	}

	@Override
	public String toString() {
		return "Emp [id=" + id + ", name=" + name + ", dept=" + dept + "]";
	}
}

對映檔案處理

<?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.sxt.dao.EmpDao">

		<resultMap type="Emp" id="basemap">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<association property="dept" javaType="Dept">
		<id property="deptid" column="deptid"/>
		<result property="deptname" column="deptname"/>
		<result property="deptdesc" column="deptdesc"/>
		</association>
		</resultMap>

	<select id="query" resultMap="basemap">
	SELECT t.*,t1.*
	FROM  t_emp t  LEFT JOIN t_dept t1
	on t.deptid=t1.deptid
	</select>
</mapper>

在這裡插入圖片描述

1對多關係

查詢出所有的部門資訊及該部門下所有員工的資訊 在這裡插入圖片描述

對映檔案

<?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.sxt.dao.DeptDao">

		<resultMap type="Dept" id="basemap">
		<id property="deptid" column="deptid"/>
		<result property="deptname" column="deptname"/>
		<result property="deptdesc" column="deptdesc"/>
		<collection property="emps" ofType="Emp">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="deptid" column="deptid"/>
		</collection>
		</resultMap>

	<select id="query" resultMap="basemap">
	SELECT t.*,t1.*
	FROM  t_dept t  LEFT JOIN t_emp t1
	on t.deptid=t1.deptid
	</select>
</mapper>

在這裡插入圖片描述

多對多,即使雙向的1對多