MyBatis入門

原文鏈接:https://blog.csdn.net/zpcandzhj/article/details/80878563

轉載自: https://blog.csdn.net/zpcandzhj/article/details/80878563


文章目錄

1.從JDBC談起

1.1.使用IDEA創建maven工程

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

1.2.引入mysql依賴包

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.32</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

這裏寫圖片描述

1.3.準備數據

  • 創建數據庫:
    CREATE DATABASE ssmdemo;

  • 創建表:
    DROP TABLE IF EXISTS tb_user;
    CREATE TABLE tb_user (
    id char(32) NOT NULL,
    user_name varchar(32) DEFAULT NULL,
    password varchar(32) DEFAULT NULL,
    name varchar(32) DEFAULT NULL,
    age int(10) DEFAULT NULL,
    sex int(2) DEFAULT NULL,
    birthday date DEFAULT NULL,
    created datetime DEFAULT NULL,
    updated datetime DEFAULT NULL,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  • 插入數據:
    INSERT INTO ssmdemo.tb_user ( userName, password, name, age, sex, birthday, created, updated) VALUES ( ‘zpc’, ‘123456’, ‘鵬程’, ‘22’, ‘1’, ‘1990-09-02’, sysdate(), sysdate());
    INSERT INTO ssmdemo.tb_user ( userName, password, name, age, sex, birthday, created, updated) VALUES ( ‘hj’, ‘123456’, ‘靜靜’, ‘22’, ‘1’, ‘1993-09-05’, sysdate(), sysdate());

1.4.JDBC基礎代碼回顧

  • JDBCTest.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**

  • @author Evan
    */
    public class JDBCTest {
    public static void main(String[] args) throws Exception {
    Connection connection = null;
    PreparedStatement prepareStatement = null;
    ResultSet rs = null;

     <span class="token keyword">try</span> <span class="token punctuation">{</span>
         <span class="token comment">// 加載驅動</span>
         Class<span class="token punctuation">.</span><span class="token function">forName</span><span class="token punctuation">(</span><span class="token string">"com.mysql.jdbc.Driver"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token comment">// 獲取連接</span>
         String url <span class="token operator">=</span> <span class="token string">"jdbc:mysql://127.0.0.1:3306/ssmdemo"</span><span class="token punctuation">;</span>
         String user <span class="token operator">=</span> <span class="token string">"root"</span><span class="token punctuation">;</span>
         String password <span class="token operator">=</span> <span class="token string">"123456"</span><span class="token punctuation">;</span>
         connection <span class="token operator">=</span> DriverManager<span class="token punctuation">.</span><span class="token function">getConnection</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> user<span class="token punctuation">,</span> password<span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token comment">// 獲取statement,preparedStatement</span>
         String sql <span class="token operator">=</span> <span class="token string">"select * from tb_user where id=?"</span><span class="token punctuation">;</span>
         prepareStatement <span class="token operator">=</span> connection<span class="token punctuation">.</span><span class="token function">prepareStatement</span><span class="token punctuation">(</span>sql<span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token comment">// 設置參數</span>
         prepareStatement<span class="token punctuation">.</span><span class="token function">setLong</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span>l<span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token comment">// 執行查詢</span>
         rs <span class="token operator">=</span> prepareStatement<span class="token punctuation">.</span><span class="token function">executeQuery</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token comment">// 處理結果集</span>
         <span class="token keyword">while</span> <span class="token punctuation">(</span>rs<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
             System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>rs<span class="token punctuation">.</span><span class="token function">getString</span><span class="token punctuation">(</span><span class="token string">"userName"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
             System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>rs<span class="token punctuation">.</span><span class="token function">getString</span><span class="token punctuation">(</span><span class="token string">"name"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
             System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>rs<span class="token punctuation">.</span><span class="token function">getInt</span><span class="token punctuation">(</span><span class="token string">"age"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
             System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>rs<span class="token punctuation">.</span><span class="token function">getDate</span><span class="token punctuation">(</span><span class="token string">"birthday"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token punctuation">}</span>
     <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
         <span class="token comment">// 關閉連接,釋放資源</span>
         <span class="token keyword">if</span> <span class="token punctuation">(</span>rs <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{</span>
             rs<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token punctuation">}</span>
         <span class="token keyword">if</span> <span class="token punctuation">(</span>prepareStatement <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{</span>
             prepareStatement<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token punctuation">}</span>
         <span class="token keyword">if</span> <span class="token punctuation">(</span>connection <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token punctuation">{</span>
             connection<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token punctuation">}</span>
     <span class="token punctuation">}</span>
    

    }
    }

1.5.JDBC缺點分析

這裏寫圖片描述

2.MyBatis介紹

這裏寫圖片描述
官方文檔 http://www.mybatis.org/mybatis-3/getting-started.html

3.Mybaits整體架構

這裏寫圖片描述
這裏寫圖片描述

4.快速入門(quick start)

4.1.引入依賴(pom.xml)

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.8</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

4.2.全局配置文件(mybatis-config.xml)

<?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>
<properties>
	<property name="driver" value="com.mysql.jdbc.Driver"/>
	<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110?useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true"/>
	<property name="username" value="root"/>
    	<property name="password" value="123456"/>
   </properties>

<!-- 環境,可以配置多個,default:指定採用哪個環境 -->
<environments default=test>
<!-- id:唯一標識 -->
<environment id=test>
<!-- 事務管理器,JDBC類型的事務管理器 -->
<transactionManager type=JDBC />
<!-- 數據源,池類型的數據源 -->
<dataSource type=POOLED>
<property name=driver value=com.mysql.jdbc.Driver />
<property name=url value=jdbc:mysql://127.0.0.1:3306/mybatis-110 />
<property name=username value=root />
<property name=password value=123456 />
</dataSource>
</environment>
<environment id=development>
<!-- 事務管理器,JDBC類型的事務管理器 -->
<transactionManager type=JDBC />
<!-- 數據源,池類型的數據源 -->
<dataSource type=POOLED>
<property name=driver value="KaTeX parse error: Expected 'EOF', got '&' at position 90: … punctuation">/&̲gt;</span></spa…{url}" />
<property name=username value="KaTeX parse error: Expected 'EOF', got '&' at position 92: … punctuation">/&̲gt;</span></spa…{password}" />
</dataSource>
</environment>
</environments>
</configuration>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

4.3.配置Map.xml(MyMapper.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:命名空間,隨便寫,一般保證命名空間唯一 -->
<mapper namespace="MyMapper">
   <!-- statement,內容:sql語句。id:唯一標識,隨便寫,在同一個命名空間下保持唯一
      resultType:sql語句查詢結果集的封裝類型,tb_user即爲數據庫中的表
    -->
   <select id="selectUser" resultType="com.zpc.mybatis.User">
      select * from tb_user where id = #{id}
   </select>
</mapper>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

4.4.修改全局配置文件(mybatis-config.xml)

配上MyMapper.xml

<?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>
   <!-- 環境,可以配置多個,default:指定採用哪個環境 -->
   <environments default="test">
      <!-- id:唯一標識 -->
      <environment id="test">
         <!-- 事務管理器,JDBC類型的事務管理器 -->
         <transactionManager type="JDBC" />
         <!-- 數據源,池類型的數據源 -->
         <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdemo" />
            <property name="username" value="root" />
            <property name="password" value="123456" />
         </dataSource>
      </environment>
   </environments>
   <mappers>
     <mapper resource="mappers/MyMapper.xml" />
   </mappers>
</configuration>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

4.5.構建sqlSessionFactory(MybatisTest.java)

		// 指定全局配置文件
        String resource = "mybatis-config.xml";
        // 讀取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 構建sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4.6.打開sqlSession會話,並執行sql(MybatisTest.java)

	    // 獲取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 操作CRUD,第一個參數:指定statement,規則:命名空間+“.”+statementId
        // 第二個參數:指定傳入sql的參數:這裏是用戶id
        User user = sqlSession.selectOne("MyMapper.selectUser", 1);
        System.out.println(user);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 完整代碼:
    MybatisTest.java
mport com.zpc.test.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class MybatisTest {
public static void main(String[] args) throws Exception {
// 指定全局配置文件
String resource = “mybatis-config.xml”;
// 讀取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
// 構建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 獲取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
// 操作CRUD,第一個參數:指定statement,規則:命名空間+“.”+statementId
// 第二個參數:指定傳入sql的參數:這裏是用戶id
User user = sqlSession.selectOne(“MyMapper.selectUser”, 1);
System.out.println(user);
} finally {
sqlSession.close();
}
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

User.java

import java.text.SimpleDateFormat;
import java.util.Date;

public class User {
private String id;
private String userName;
private String password;
private String name;
private Integer age;
private Integer sex;
private Date birthday;
private String created;
private String updated;

<span class="token keyword">public</span> String <span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> id<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setId</span><span class="token punctuation">(</span>String id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>id <span class="token operator">=</span> id<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> String <span class="token function">getUserName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> userName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setUserName</span><span class="token punctuation">(</span>String userName<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>userName <span class="token operator">=</span> userName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> String <span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> password<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setPassword</span><span class="token punctuation">(</span>String password<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>password <span class="token operator">=</span> password<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> String <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setName</span><span class="token punctuation">(</span>String name<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> Integer <span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setAge</span><span class="token punctuation">(</span>Integer age<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> Integer <span class="token function">getSex</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> sex<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setSex</span><span class="token punctuation">(</span>Integer sex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>sex <span class="token operator">=</span> sex<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> Date <span class="token function">getBirthday</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> birthday<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setBirthday</span><span class="token punctuation">(</span>Date birthday<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>birthday <span class="token operator">=</span> birthday<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> String <span class="token function">getCreated</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> created<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setCreated</span><span class="token punctuation">(</span>String created<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>created <span class="token operator">=</span> created<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> String <span class="token function">getUpdated</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> updated<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setUpdated</span><span class="token punctuation">(</span>String updated<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>updated <span class="token operator">=</span> updated<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> String <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">"User{"</span> <span class="token operator">+</span>
            <span class="token string">"id='"</span> <span class="token operator">+</span> id <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
            <span class="token string">", userName='"</span> <span class="token operator">+</span> userName <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
            <span class="token string">", password='"</span> <span class="token operator">+</span> password <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
            <span class="token string">", name='"</span> <span class="token operator">+</span> name <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
            <span class="token string">", age="</span> <span class="token operator">+</span> age <span class="token operator">+</span>
            <span class="token string">", sex="</span> <span class="token operator">+</span> sex <span class="token operator">+</span>
            <span class="token string">", birthday='"</span> <span class="token operator">+</span> <span class="token keyword">new</span> <span class="token class-name">SimpleDateFormat</span><span class="token punctuation">(</span><span class="token string">"yyyy-MM-dd"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>birthday<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
            <span class="token string">", created='"</span> <span class="token operator">+</span> created <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
            <span class="token string">", updated='"</span> <span class="token operator">+</span> updated <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span>
            <span class="token string">'}'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

4.7.目錄結構

這裏寫圖片描述

5.分析

5.1.引入日誌依賴包(pom.xml)

會自動引入log4j以及slf4j-api

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.5</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

5.2.添加log4j.properties

log4j.rootLogger=DEBUG,A1
log4j.logger.org.apache=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
  • 1
  • 2
  • 3
  • 4
  • 5

再次運行程序會打印日誌:

2018-06-30 19:53:37,554 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2018-06-30 19:53:37,818 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 2094411587.
2018-06-30 19:53:37,818 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7cd62f43]
2018-06-30 19:53:37,863 [main] [MyMapper.selectUser]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
2018-06-30 19:53:37,931 [main] [MyMapper.selectUser]-[DEBUG] ==> Parameters: 1(Integer)
2018-06-30 19:53:37,953 [main] [MyMapper.selectUser]-[DEBUG] <==      Total: 1
User{id='1', userName='zpc', password='123456', name='鵬程', age=25, sex=1, birthday='1990-09-02', created='2018-06-30 18:20:18.0', updated='2018-06-30 18:20:18.0'}
2018-06-30 19:53:37,954 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7cd62f43]
2018-06-30 19:53:37,954 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7cd62f43]
2018-06-30 19:53:37,955 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 2094411587 to pool.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5.3.MyBatis使用步驟總結

1)配置mybatis-config.xml 全局的配置文件 (1、數據源,2、外部的mapper)
2)創建SqlSessionFactory
3)通過SqlSessionFactory創建SqlSession對象
4)通過SqlSession操作數據庫 CRUD
5)調用session.commit()提交事務
6)調用session.close()關閉會話

6.完整的CRUD操作

6.1.創建UserDao接口

import com.zpc.mybatis.pojo.User;
import java.util.List;

public interface UserDao {

<span class="token comment">/**
 * 根據id查詢用戶信息
 *
 * @param id
 * @return
 */</span>
<span class="token keyword">public</span> User <span class="token function">queryUserById</span><span class="token punctuation">(</span>String id<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/**
 * 查詢所有用戶信息
 *
 * @return
 */</span>
<span class="token keyword">public</span> List<span class="token generics function"><span class="token punctuation">&lt;</span>User<span class="token punctuation">&gt;</span></span> <span class="token function">queryUserAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/**
 * 新增用戶
 *
 * @param user
 */</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">insertUser</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/**
 * 更新用戶信息
 *
 * @param user
 */</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">updateUser</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/**
 * 根據id刪除用戶信息
 *
 * @param id
 */</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">deleteUser</span><span class="token punctuation">(</span>String id<span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

6.2.創建UserDaoImpl

import com.zpc.mybatis.dao.UserDao;
import com.zpc.mybatis.pojo.User;
import org.apache.ibatis.session.SqlSession;
import java.util.List;

public class UserDaoImpl implements UserDao {
public SqlSession sqlSession;

<span class="token keyword">public</span> <span class="token function">UserDaoImpl</span><span class="token punctuation">(</span>SqlSession sqlSession<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>sqlSession <span class="token operator">=</span> sqlSession<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> User <span class="token function">queryUserById</span><span class="token punctuation">(</span>String id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>sqlSession<span class="token punctuation">.</span><span class="token function">selectOne</span><span class="token punctuation">(</span><span class="token string">"UserDao.queryUserById"</span><span class="token punctuation">,</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> List<span class="token generics function"><span class="token punctuation">&lt;</span>User<span class="token punctuation">&gt;</span></span> <span class="token function">queryUserAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>sqlSession<span class="token punctuation">.</span><span class="token function">selectList</span><span class="token punctuation">(</span><span class="token string">"UserDao.queryUserAll"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">insertUser</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>sqlSession<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span><span class="token string">"UserDao.insertUser"</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">updateUser</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>sqlSession<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span><span class="token string">"UserDao.updateUser"</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">deleteUser</span><span class="token punctuation">(</span>String id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>sqlSession<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token string">"UserDao.deleteUser"</span><span class="token punctuation">,</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

    6.3.編寫UserDao對應的UserDaoMapper.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:命名空間,隨便寫,一般保證命名空間唯一 -->
    <mapper namespace="UserDao">
        <!-- statement,內容:sql語句。id:唯一標識,隨便寫,在同一個命名空間下保持唯一
           resultType:sql語句查詢結果集的封裝類型,tb_user即爲數據庫中的表
         -->
        <!--<select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">-->
        <!--select * from tb_user where id = #{id}-->
        <!--</select>-->
    
    <span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span>使用別名<span class="token operator">--</span><span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span>select id<span class="token operator">=</span><span class="token string">"queryUserById"</span> resultType<span class="token operator">=</span><span class="token string">"com.zpc.mybatis.pojo.User"</span><span class="token operator">&gt;</span>
      select
       tuser<span class="token punctuation">.</span>id as id<span class="token punctuation">,</span>
       tuser<span class="token punctuation">.</span>user_name as userName<span class="token punctuation">,</span>
       tuser<span class="token punctuation">.</span>password as password<span class="token punctuation">,</span>
       tuser<span class="token punctuation">.</span>name as name<span class="token punctuation">,</span>
       tuser<span class="token punctuation">.</span>age as age<span class="token punctuation">,</span>
       tuser<span class="token punctuation">.</span>birthday as birthday<span class="token punctuation">,</span>
       tuser<span class="token punctuation">.</span>sex as sex<span class="token punctuation">,</span>
       tuser<span class="token punctuation">.</span>created as created<span class="token punctuation">,</span>
       tuser<span class="token punctuation">.</span>updated as updated
       from
       tb_user tuser
       where tuser<span class="token punctuation">.</span>id <span class="token operator">=</span> #<span class="token punctuation">{</span>id<span class="token punctuation">}</span><span class="token punctuation">;</span>
    

    </select>

    <span class="token operator">&lt;</span>select id<span class="token operator">=</span><span class="token string">"queryUserAll"</span> resultType<span class="token operator">=</span><span class="token string">"com.zpc.mybatis.pojo.User"</span><span class="token operator">&gt;</span>
        select <span class="token operator">*</span> from tb_user<span class="token punctuation">;</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span>select<span class="token operator">&gt;</span>
    
    <span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span>插入數據<span class="token operator">--</span><span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span>insert id<span class="token operator">=</span><span class="token string">"insertUser"</span> parameterType<span class="token operator">=</span><span class="token string">"com.zpc.mybatis.pojo.User"</span><span class="token operator">&gt;</span>
        INSERT INTO tb_user <span class="token punctuation">(</span>
        user_name<span class="token punctuation">,</span>
        password<span class="token punctuation">,</span>
        name<span class="token punctuation">,</span>
        age<span class="token punctuation">,</span>
        sex<span class="token punctuation">,</span>
        birthday<span class="token punctuation">,</span>
        created<span class="token punctuation">,</span>
        updated
        <span class="token punctuation">)</span>
        VALUES
        <span class="token punctuation">(</span>
        #<span class="token punctuation">{</span>userName<span class="token punctuation">}</span><span class="token punctuation">,</span>
        #<span class="token punctuation">{</span>password<span class="token punctuation">}</span><span class="token punctuation">,</span>
        #<span class="token punctuation">{</span>name<span class="token punctuation">}</span><span class="token punctuation">,</span>
        #<span class="token punctuation">{</span>age<span class="token punctuation">}</span><span class="token punctuation">,</span>
        #<span class="token punctuation">{</span>sex<span class="token punctuation">}</span><span class="token punctuation">,</span>
        #<span class="token punctuation">{</span>birthday<span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span>insert<span class="token operator">&gt;</span>
    
    <span class="token operator">&lt;</span>update id<span class="token operator">=</span><span class="token string">"updateUser"</span> parameterType<span class="token operator">=</span><span class="token string">"com.zpc.mybatis.pojo.User"</span><span class="token operator">&gt;</span>
        UPDATE tb_user
        <span class="token operator">&lt;</span>trim prefix<span class="token operator">=</span><span class="token string">"set"</span> suffixOverrides<span class="token operator">=</span><span class="token string">","</span><span class="token operator">&gt;</span>
            <span class="token operator">&lt;</span><span class="token keyword">if</span> test<span class="token operator">=</span><span class="token string">"userName!=null"</span><span class="token operator">&gt;</span>user_name <span class="token operator">=</span> #<span class="token punctuation">{</span>userName<span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token keyword">if</span><span class="token operator">&gt;</span>
            <span class="token operator">&lt;</span><span class="token keyword">if</span> test<span class="token operator">=</span><span class="token string">"password!=null"</span><span class="token operator">&gt;</span>password <span class="token operator">=</span> #<span class="token punctuation">{</span>password<span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token keyword">if</span><span class="token operator">&gt;</span>
            <span class="token operator">&lt;</span><span class="token keyword">if</span> test<span class="token operator">=</span><span class="token string">"name!=null"</span><span class="token operator">&gt;</span>name <span class="token operator">=</span> #<span class="token punctuation">{</span>name<span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token keyword">if</span><span class="token operator">&gt;</span>
            <span class="token operator">&lt;</span><span class="token keyword">if</span> test<span class="token operator">=</span><span class="token string">"age!=null"</span><span class="token operator">&gt;</span>age <span class="token operator">=</span> #<span class="token punctuation">{</span>age<span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token keyword">if</span><span class="token operator">&gt;</span>
            <span class="token operator">&lt;</span><span class="token keyword">if</span> test<span class="token operator">=</span><span class="token string">"sex!=null"</span><span class="token operator">&gt;</span>sex <span class="token operator">=</span> #<span class="token punctuation">{</span>sex<span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token keyword">if</span><span class="token operator">&gt;</span>
            <span class="token operator">&lt;</span><span class="token keyword">if</span> test<span class="token operator">=</span><span class="token string">"birthday!=null"</span><span class="token operator">&gt;</span>birthday <span class="token operator">=</span> #<span class="token punctuation">{</span>birthday<span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token keyword">if</span><span class="token operator">&gt;</span>
            updated <span class="token operator">=</span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token operator">&lt;</span><span class="token operator">/</span>trim<span class="token operator">&gt;</span>
        WHERE
        <span class="token punctuation">(</span>id <span class="token operator">=</span> #<span class="token punctuation">{</span>id<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span>update<span class="token operator">&gt;</span>
    
    <span class="token operator">&lt;</span>delete id<span class="token operator">=</span><span class="token string">"deleteUser"</span><span class="token operator">&gt;</span>
        delete from tb_user where id<span class="token operator">=</span>#<span class="token punctuation">{</span>id<span class="token punctuation">}</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span>delete<span class="token operator">&gt;</span>
    

    </mapper>

    在mybatis-config.xml中添加配置:

    <mappers>
        <mapper resource="mappers/MyMapper.xml"/>
        <mapper resource="mappers/UserDaoMapper.xml"/>
    </mappers>
    
    • 1
    • 2
    • 3
    • 4

    6.4.添加UserDao的測試用例

    Pom文件中添加junit依賴

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    按住Alt+Enter,選擇create test
    這裏寫圖片描述

    這裏寫圖片描述

    6.5.編寫UserDao的測試用例

    import com.zpc.mybatis.dao.UserDao;
    import com.zpc.mybatis.dao.impl.UserDaoImpl;
    import com.zpc.mybatis.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Before;
    import org.junit.Test;
    import java.io.InputStream;
    import java.util.Date;
    import java.util.List;
    

    public class UserDaoTest {

    public UserDao userDao;
    public SqlSession sqlSession;
    
    @Before
    public void setUp() throws Exception {
        // mybatis-config.xml
        String resource = "mybatis-config.xml";
        // 讀取配置文件
        InputStream is = Resources.getResourceAsStream(resource);
        // 構建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        // 獲取sqlSession
        sqlSession = sqlSessionFactory.openSession();
        this.userDao = new UserDaoImpl(sqlSession);
    }
    
    @Test
    public void queryUserById() throws Exception {
        System.out.println(this.userDao.queryUserById("1"));
    }
    
    @Test
    public void queryUserAll() throws Exception {
        List&lt;User&gt; userList = this.userDao.queryUserAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }
    
    @Test
    public void insertUser() throws Exception {
        User user = new User();
        user.setAge(16);
        user.setBirthday(new Date("1990/09/02"));
        user.setName("大鵬");
        user.setPassword("123456");
        user.setSex(1);
        user.setUserName("evan");
        this.userDao.insertUser(user);
        this.sqlSession.commit();
    }
    
    @Test
    public void updateUser() throws Exception {
        User user = new User();
        user.setBirthday(new Date());
        user.setName("靜鵬");
        user.setPassword("654321");
        user.setSex(1);
        user.setUserName("evanjin");
        user.setId("1");
        this.userDao.updateUser(user);
        this.sqlSession.commit();
    }
    
    @Test
    public void deleteUser() throws Exception {
        this.userDao.deleteUser("4");
        this.sqlSession.commit();
    }
    

    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    6.6.目錄結構

    這裏寫圖片描述

    6.7.解決數據庫字段名和實體類屬性名不一致的問題

    查詢數據的時候,發現查不到userName的信息,
    User{id=‘2’, userName=‘null’, password=‘123456’, name=‘靜靜’, age=22, sex=0, birthday=‘1993-09-05’, created=‘2018-06-30 18:22:28.0’, updated=‘2018-06-30 18:22:28.0’}
    原因:數據庫的字段名是user_name,POJO中的屬性名字是userName
    兩端不一致,造成mybatis無法填充對應的字段信息。修改方法:在sql語句中使用別名。
    解決方案1:在sql語句中使用別名:

    <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">
       select
        tuser.id as id,
        tuser.user_name as userName,
        tuser.password as password,
        tuser.name as name,
        tuser.age as age,
        tuser.birthday as birthday,
        tuser.sex as sex,
        tuser.created as created,
        tuser.updated as updated
        from
        tb_user tuser
        where tuser.id = #{id};
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    解決方案2: 參考後面的resultMap –mapper具體的配置的時候

    解決方案3:參考駝峯匹配 — mybatis-config.xml 的時候

    7. 動態代理Mapper實現類

    7.1.思考上述CRUD中的問題

    1、接口->實現類->mapper.xml
    2、實現類中,使用mybatis的方式非常類似
    3、xml中的sql statement 硬編碼到java代碼中。

    思考:能否只寫接口,不寫實現類。只編寫接口和Mapper.xml即可?

    因爲在dao(mapper)的實現類中對sqlsession的使用方式很類似。因此mybatis提供了接口的動態代理。

    7.2.使用動態代理改造CRUD

    • 修改測試用例的setUp方法
      這裏寫圖片描述
    • 執行queryUserAll()方法

    這裏寫圖片描述

    org.apache.ibatis.binding.BindingException: Type interface com.zpc.mybatis.dao.UserDao is not known to the MapperRegistry.
    	at org.apache.ibatis.binding.MapperRegistry.getMapper(MapperRegistry.java:47)
    	at org.apache.ibatis.session.Configuration.getMapper(Configuration.java:655)
    	at org.apache.ibatis.session.defaults.DefaultSqlSession.getMapper(DefaultSqlSession.java:222)
    at com.zpc.mybatis.test.UserDaoTest.setUp(UserDaoTest.java:32)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 分析原因,在UserMapper.xml中配置接口的全路徑
      mapper.xml namespace
      如果希望使用mybatis通過的動態代理的接口,就需要namespace中的值,和需要對應的Mapper(dao)接口的全路徑一致。Mapper中Namespace的定義本身是沒有限制的,只要不重複即可,但如果使用Mybatis的DAO接口動態代理,則namespace必須爲DAO接口的全路徑,例如:com.zpc.mybatis.dao.UserDao
    <mapper namespace="com.zpc.mybatis.dao.UserDao">
    
    • 1

    7.3.完整的例子

    1、創建UserMapper接口(對應原UserDao)

    public interface UserMapper {
    

    /**
    * 登錄(直接使用註解指定傳入參數名稱)
    * @param userName
    * @param password
    * @return
    */
    public User login(@Param(“userName”) String userName, @Param(“password”) String password);

    /**
    * 根據表名查詢用戶信息(直接使用註解指定傳入參數名稱)
    * @param tableName
    * @return
    */
    public List<User> queryUserByTableName(@Param(“tableName”) String tableName);

    /**
    * 根據Id查詢用戶信息
    * @param id
    * @return
    */
    public User queryUserById(Long id);

    /**
    * 查詢所有用戶信息
    * @return
    */
    public List<User> queryUserAll();

    /**
    * 新增用戶信息
    * @param user
    */
    public void insertUser(User user);

    /**
    * 根據id更新用戶信息
    * @param user
    */
    public void updateUser(User user);

    /**
    * 根據id刪除用戶信息
    * @param id
    */
    public void deleteUserById(Long id);
    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    2、創建UserMapper.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:命名空間,隨便寫,一般保證命名空間唯一 ,爲了使用接口動態代理,這裏必須是接口的全路徑名-->
    <mapper namespace="com.zpc.mybatis.dao.UserMapper">
        <!--
           1.#{},預編譯的方式preparedstatement,使用佔位符替換,防止sql注入,一個參數的時候,任意參數名可以接收
           2.${},普通的Statement,字符串直接拼接,不可以防止sql注入,一個參數的時候,必須使用${value}接收參數
         -->
        <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
            select * from ${tableName}
        </select>
    
    &lt;select id="login" resultType="com.zpc.mybatis.pojo.User"&gt;
        select * from tb_user where user_name = #{userName} and password = #{password}
    &lt;/select&gt;
    
    &lt;!-- statement,內容:sql語句。
       id:唯一標識,隨便寫,在同一個命名空間下保持唯一,使用動態代理之後要求和方法名保持一致
       resultType:sql語句查詢結果集的封裝類型,使用動態代理之後和方法的返回類型一致;resultMap:二選一
       parameterType:參數的類型,使用動態代理之後和方法的參數類型一致
     --&gt;
    &lt;select id="queryUserById" resultType="com.zpc.mybatis.pojo.User"&gt;
        select * from tb_user where id = #{id}
    &lt;/select&gt;
    &lt;select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User"&gt;
        select * from tb_user
    &lt;/select&gt;
    &lt;!-- 新增的Statement
       id:唯一標識,隨便寫,在同一個命名空間下保持唯一,使用動態代理之後要求和方法名保持一致
       parameterType:參數的類型,使用動態代理之後和方法的參數類型一致
       useGeneratedKeys:開啓主鍵回寫
       keyColumn:指定數據庫的主鍵
       keyProperty:主鍵對應的pojo屬性名
     --&gt;
    &lt;insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id"
            parameterType="com.zpc.mybatis.pojo.User"&gt;
        INSERT INTO tb_user (
        id,
        user_name,
        password,
        name,
        age,
        sex,
        birthday,
        created,
        updated
        )
        VALUES
        (
        null,
        #{userName},
        #{password},
        #{name},
        #{age},
        #{sex},
        #{birthday},
        NOW(),
        NOW()
        );
    &lt;/insert&gt;
    &lt;!-- 
       更新的statement
       id:唯一標識,隨便寫,在同一個命名空間下保持唯一,使用動態代理之後要求和方法名保持一致
       parameterType:參數的類型,使用動態代理之後和方法的參數類型一致
     --&gt;
    &lt;update id="updateUser" parameterType="com.zpc.mybatis.pojo.User"&gt;
        UPDATE tb_user
        &lt;trim prefix="set" suffixOverrides=","&gt;
            &lt;if test="userName!=null"&gt;user_name = #{userName},&lt;/if&gt;
            &lt;if test="password!=null"&gt;password = #{password},&lt;/if&gt;
            &lt;if test="name!=null"&gt;name = #{name},&lt;/if&gt;
            &lt;if test="age!=null"&gt;age = #{age},&lt;/if&gt;
            &lt;if test="sex!=null"&gt;sex = #{sex},&lt;/if&gt;
            &lt;if test="birthday!=null"&gt;birthday = #{birthday},&lt;/if&gt;
            updated = now(),
        &lt;/trim&gt;
        WHERE
        (id = #{id});
    &lt;/update&gt;
    &lt;!-- 
       刪除的statement
       id:唯一標識,隨便寫,在同一個命名空間下保持唯一,使用動態代理之後要求和方法名保持一致
       parameterType:參數的類型,使用動態代理之後和方法的參數類型一致
     --&gt;
    &lt;delete id="deleteUserById" parameterType="java.lang.String"&gt;
        delete from tb_user where id=#{id}
    &lt;/delete&gt;
    

    </mapper>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    3、全局配置文件mybatis-config.xml引入UserMapper.xml

    <mappers>
        <mapper resource="mappers/MyMapper.xml"/>
        <mapper resource="mappers/UserDaoMapper.xml"/>
        <mapper resource="mappers/UserMapper.xml"/>
    </mappers>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4、創建UserMapper測試用例

    import com.zpc.mybatis.dao.UserMapper;
    import com.zpc.mybatis.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Before;
    import org.junit.Test;
    

    import java.io.InputStream;
    import java.util.Date;
    import java.util.List;

    public class UserMapperTest {

    public UserMapper userMapper;
    
    @Before
    public void setUp() throws Exception {
        // 指定配置文件
        String resource = "mybatis-config.xml";
        // 讀取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 構建sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 獲取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
    
        // 1. 映射文件的命名空間(namespace)必須是mapper接口的全路徑
        // 2. 映射文件的statement的id必須和mapper接口的方法名保持一致
        // 3. Statement的resultType必須和mapper接口方法的返回類型一致
        // 4. statement的parameterType必須和mapper接口方法的參數類型一致(不一定)
        this.userMapper = sqlSession.getMapper(UserMapper.class);
    }
    
    @Test
    public void testQueryUserByTableName() {
        List&lt;User&gt; userList = this.userMapper.queryUserByTableName("tb_user");
        for (User user : userList) {
            System.out.println(user);
        }
    }
    
    @Test
    public void testLogin() {
        System.out.println(this.userMapper.login("hj", "123456"));
    }
    
    @Test
    public void testQueryUserById() {
        System.out.println(this.userMapper.queryUserById("1"));
    }
    
    @Test
    public void testQueryUserAll() {
        List&lt;User&gt; userList = this.userMapper.queryUserAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }
    
    @Test
    public void testInsertUser() {
        User user = new User();
        user.setAge(20);
        user.setBirthday(new Date());
        user.setName("大神");
        user.setPassword("123456");
        user.setSex(2);
        user.setUserName("bigGod222");
        this.userMapper.insertUser(user);
        System.out.println(user.getId());
    }
    
    @Test
    public void testUpdateUser() {
        User user = new User();
        user.setBirthday(new Date());
        user.setName("靜靜");
        user.setPassword("123456");
        user.setSex(0);
        user.setUserName("Jinjin");
        user.setId("1");
        this.userMapper.updateUser(user);
    }
    
    @Test
    public void testDeleteUserById() {
        this.userMapper.deleteUserById("1");
    }
    

    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    目錄結構:
    這裏寫圖片描述

    7.4.動態代理總結

    這裏寫圖片描述

    8.mybatis-config.xml詳解

    mybatis-config.xml講究嚴格的順序,具體順序遵循文檔的順序
    這裏寫圖片描述

    8.1.properties屬性讀取外部資源

    properties配置的屬性都是可外部配置且可動態替換的,既可以在典型的 Java 屬性文件中配置,亦可通過 properties 元素的子元素來傳遞。例如:

    <properties resource="org/mybatis/example/config.properties">
      <property name="username" value="dev_user"/>
      <property name="password" value="F2Fa3!33TYyg"/>
    </properties>
    
    • 1
    • 2
    • 3
    • 4

    然後其中的屬性就可以在整個配置文件中被用來替換需要動態配置的屬性值。比如:

    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    這個例子中的 username 和 password 將會由 properties 元素中設置的相應值來替換。 driver 和 url 屬性將會由 config.properties 文件中對應的值來替換。這樣就爲配置提供了諸多靈活選擇。

    屬性也可以被傳遞到 SqlSessionFactoryBuilder.build()方法中。例如:

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);
    // ... or ...
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);
    
    • 1
    • 2
    • 3

    如果屬性在不只一個地方進行了配置,那麼 MyBatis 將按照下面的順序來加載:
    1)在 properties 元素體內指定的屬性首先被讀取。
    2)然後根據 properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據 url 屬性指定的路徑讀取屬性文件,並覆蓋已讀取的同名屬性。
    3)最後讀取作爲方法參數傳遞的屬性,並覆蓋已讀取的同名屬性。
    因此,通過方法參數傳遞的屬性具有最高優先級,resource/url 屬性中指定的配置文件次之,最低優先級的是 properties 屬性中指定的屬性。

    8.2.settings設置

    這裏寫圖片描述

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
    • 1
    • 2
    • 3

    測試:
    沒有開啓駝峯匹配:

    2018-07-01 13:57:56,486 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
    2018-07-01 13:57:56,524 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
    2018-07-01 13:57:56,568 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
    User{id='1', userName='null', password='123456', name='大神', age=20, sex=2, birthday='2018-07-01', created='2018-07-01 13:36:09.0', updated='2018-07-01 13:36:09.0'}
    
    • 1
    • 2
    • 3
    • 4

    開啓駝峯匹配:

    2018-07-01 13:58:40,599 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
    2018-07-01 13:58:40,642 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
    2018-07-01 13:58:40,661 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
    User{id='1', userName='bigGod222', password='123456', name='大神', age=20, sex=2, birthday='2018-07-01', created='2018-07-01 13:36:09.0', updated='2018-07-01 13:36:09.0'}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    8.3.typeAliases

    類型別名是爲 Java 類型命名的一個短的名字。它只和 XML 配置有關,存在的意義僅在於用來減少類完全限定名的冗餘。

    <typeAliases>
        <typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/>
    </typeAliases>
    
    • 1
    • 2
    • 3

    缺點:每個pojo類都要去配置。
    解決方案:使用掃描包,掃描指定包下的所有類,掃描之後的別名就是類名(不區分大小寫),建議使用的時候和類名一致。

    <typeAliases>
        <!--type:實體類的全路徑。alias:別名,通常首字母大寫-->
        <!--<typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/>-->
        <package name="com.zpc.mybatis.pojo"/>
    </typeAliases>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Mybatis已經爲普通的 Java 類型內建了許多相應的類型別名。它們都是大小寫不敏感的.
    這裏寫圖片描述

    8.4.typeHandlers(類型處理器)

    無論是 MyBatis 在預處理語句(PreparedStatement)中設置一個參數時,還是從結果集中取出一個值時, 都會用類型處理器將獲取的值以合適的方式轉換成 Java 類型。可以重寫類型處理器或創建你自己的類型處理器來處理不支持的或非標準的類型。

    8.5.plugins(插件)攔截器

    MyBatis 允許你在已映射語句執行過程中的某一點進行攔截調用。默認情況下,MyBatis 允許使用插件來攔截的方法調用包括:
    Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
    ParameterHandler (getParameterObject, setParameters)
    ResultSetHandler (handleResultSets, handleOutputParameters)
    StatementHandler (prepare, parameterize, batch, update, query)

    現在一些MyBatis 插件比如PageHelper都是基於這個原理,有時爲了監控sql執行效率,也可以使用插件機制
    原理:
    這裏寫圖片描述
    自定義攔截器:

    // ExamplePlugin.java
    @Intercepts({@Signature(
      type= Executor.class,
      method = "update",
      args = {MappedStatement.class,Object.class})})
    public class ExamplePlugin implements Interceptor {
      public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed();
      }
      public Object plugin(Object target) {
        return Plugin.wrap(target, this);
      }
      public void setProperties(Properties properties) {
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    配置:

    <!-- mybatis-config.xml -->
    <plugins>
      <plugin interceptor="org.mybatis.example.ExamplePlugin">
        <property name="someProperty" value="100"/>
      </plugin>
    </plugins>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面的插件將會攔截在 Executor 實例中所有的 “update” 方法調用, 這裏的 Executor 是負責執行低層映射語句的內部對象。

    8.6.environments(環境)

    MyBatis 可以配置成適應多種環境,例如,開發、測試和生產環境需要有不同的配置;
    儘管可以配置多個環境,每個 SqlSessionFactory 實例只能選擇其一。
    雖然,這種方式也可以做到很方便的分離多個環境,但是實際使用場景下,我們更多的是選擇使用spring來管理數據源,來做到環境的分離。

    8.7.mappers

    需要告訴 MyBatis 到哪裏去找到 SQL 映射語句。即告訴 MyBatis 到哪裏去找映射文件。你可以使用相對於類路徑的資源引用, 或完全限定資源定位符(包括 file:/// 的 URL),或類名和包名等。例如:

    <!-- 使用相對於類路徑的資源引用 -->
    <mappers>
      <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
      <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
      <mapper resource="org/mybatis/builder/PostMapper.xml"/>
    </mappers>
    

    <!-- 使用映射器接口實現類的完全限定類名 -->
    <mappers>
    <mapper class=“org.mybatis.builder.AuthorMapper”/>
    <mapper class=“org.mybatis.builder.BlogMapper”/>
    <mapper class=“org.mybatis.builder.PostMapper”/>
    </mappers>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    這裏所謂的mapper接口路徑。實際上就是dao的接口路徑。在mybatis中,通常把dao的包叫做mapper。類名,也叫做mapper
    1、定義一個接口。
    2、在接口所在的包中定義mapper.xml,並且要求xml文件和interface的名稱要相同。
    3、在mybatis-config.xml 中通過class路徑,引入mapper(註解方式)。要求mapper.xml 中的名稱空間是類的接口的全路徑。

    註解方式:

    <mappers>
        <mapper resource="mappers/MyMapper.xml"/>
        <mapper resource="mappers/UserDaoMapper.xml"/>
        <!--註解方式可以使用如下配置方式-->
        <mapper class="com.zpc.mybatis.dao.UserMapper"/>
    </mappers>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    問題:
    1、mapper.xml 和 java文件沒有分離。 之後的教程講述和spring整合之後解決。
    2、需要一個一個的去加載mapper。

    當然也可以使用包掃描(必須使用註解方式,即在接口方法上使用註解,如@Select("select * from tb_user ")):

    缺點:
    1、如果包的路徑有很多?
    2、mapper.xml和mapper.java沒有分離。
    spring整合的時候解決。

    9.Mapper XML文件詳解

    9.1.CRUD標籤

    9.1.1.select

    select – 書寫查詢sql語句
    select中的幾個屬性說明:
    id屬性:當前名稱空間下的statement的唯一標識。必須。要求id和mapper接口中的方法的名字一致。
    resultType:將結果集映射爲java的對象類型。必須(和 resultMap 二選一)
    parameterType:傳入參數類型。可以省略

    9.1.2.insert

    insert 的幾個屬性說明:
    id:唯一標識,隨便寫,在同一個命名空間下保持唯一,使用動態代理之後要求和方法名保持一致
    parameterType:參數的類型,使用動態代理之後和方法的參數類型一致
    useGeneratedKeys:開啓主鍵回寫
    keyColumn:指定數據庫的主鍵
    keyProperty:主鍵對應的pojo屬性名
    標籤內部:具體的sql語句。

    9.1.3.update

    id屬性:當前名稱空間下的statement的唯一標識(必須屬性);
    parameterType:傳入的參數類型,可以省略。
    標籤內部:具體的sql語句。

    9.1.4.delete

    delete 的幾個屬性說明:
    id屬性:當前名稱空間下的statement的唯一標識(必須屬性);
    parameterType:傳入的參數類型,可以省略。
    標籤內部:具體的sql語句。

    9.2.#{}和${}

    場景:數據庫有兩個一模一樣的表。歷史表,當前表
    查詢表中的信息,有時候從歷史表中去查詢數據,有時候需要去新的表去查詢數據。
    希望使用1個方法來完成操作。

    <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
        select * from #{tableName}
    </select>
    

    /**

    • 根據表名查詢用戶信息(直接使用註解指定傳入參數名稱)
    • @param tableName
    • @return
      */
      public List<User> queryUserByTableName(String tableName);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    測試輸出:
    這裏寫圖片描述
    有問題,報語法錯誤:相當於執行了這樣一條sql:
    select * from “tb_user”;
    顯然表名多了引號。

    改正:

    <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
        select * from ${tableName}
    </select>
    
    • 1
    • 2
    • 3

    注意:
    #{} 只是替換?,相當於PreparedStatement使用佔位符去替換參數,可以防止sql注入。
    ${} 是進行字符串拼接,相當於sql語句中的Statement,使用字符串去拼接sql;$可以是sql中的任一部分傳入到Statement中,不能防止sql注入。

    使用${} 去取出參數值信息,需要使用${value}
    #{} 只是表示佔位,與參數的名字無關,如果只有一個參數,會自動對應。

    推薦:

    /**
     * 根據表名查詢用戶信息(直接使用註解指定傳入參數名稱)
     *
     * @param tableName
     * @return
     */
    public List<User> queryUserByTableName(@Param("tableName") String tableName);
    

    <select id=“queryUserByTableName” resultType=“com.zpc.mybatis.pojo.User”>
    select * from ${tableName}
    </select>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    #{}多個參數時:

    /**
     * 登錄(直接使用註解指定傳入參數名稱)
     *
     * @param userName
     * @param password
     * @return
     */
    public User login( String userName, String password);
    

    <select id=“login” resultType=“com.zpc.mybatis.pojo.User”>
    select * from tb_user where user_name = #{userName} and password = #{password}
    </select>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    報錯:

    org.apache.ibatis.exceptions.PersistenceException: 
    ### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found. Available parameters are [0, 1, param1, param2]
    ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found. Available parameters are [0, 1, param1, param2]
    
    • 1
    • 2
    • 3

    解決方案一:

    <select id="login" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where user_name = #{0} and password = #{1}
    </select>
    
    • 1
    • 2
    • 3

    解決方案二:

    <select id="login" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where user_name = #{param1} and password = #{param2}
    </select>
    
    • 1
    • 2
    • 3

    最終解決方案:

    /**
     * 登錄(直接使用註解指定傳入參數名稱)
     *
     * @param userName
     * @param password
     * @return
     */
    public User login(@Param("userName") String userName, @Param("password") String password);
    

    <select id=“login” resultType=“com.zpc.mybatis.pojo.User”>
    select * from tb_user where user_name = #{userName} and password = #{password}
    </select>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    通常在方法的參數列表上加上一個註釋@Param(“xxxx”) 顯式指定參數的名字,然後通過${“xxxx”}或#{“xxxx”}
    sql語句動態生成的時候,使用${};
    sql語句中某個參數進行佔位的時候#{}

    9.3.面試題(#、$區別)

    /**
     * #號
     * @param username1
     * @return
     */
    User queryUserListByName1(@Param("username1") String username1);
    

    /**

    • $號
    • @param username2
    • @return
      */
      User queryUserListByName2(@Param(“username2”) String username2);

    <select id=“queryUserListByName1” resultType=“com.zpc.mybatis.pojo.User”>
    select * from tb_user WHERE user_name=#{username1}
    </select>

    <select id=“queryUserListByName2” resultType=“com.zpc.mybatis.pojo.User”>
    select * from tb_user WHERE user_name=’${username2}’//手動加了引號
    </select>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    9.4.resultMap

    這裏寫圖片描述
    這裏寫圖片描述
    使用:
    這裏寫圖片描述

    9.5.sql片段

    <sql id=””></sql>
    <include refId=”” />
    
    • 1
    • 2

    例如在UserMapper.xml中定義如下片段:

    <sql id="commonSql">
    		id,
    			user_name,
    			password,
    			name,
    			age,
    			sex,
    			birthday,
    			created,
    			updated	
    </sql> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    則可以在UserMapper.xml中使用它:

    <select id="queryUserById" resultMap="userResultMap">
    	select <include refid="commonSql"></include> from tb_user where id = #{id}
    </select>
    

    <select id=“queryUsersLikeUserName” resultType=“User”>
    select <include refid=“commonSql”></include> from tb_user where user_name like “%”#{userName}"%"
    </select>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Sql片段也可以定義在單獨的.xml文件中如:
    定義CommonSQL.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="CommonSQL">
    	<sql id="commonSql">
    		id,
    			user_name,
    			password,
    			name,
    			age,
    			sex,
    			birthday,
    			created,
    			updated	
    	</sql>
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    使用:

    	<select id="queryUserById" resultMap="userResultMap">
    		select <include refid="CommonSQL.commonSql"></include> from tb_user where id = #{id}
    	</select>
    
    &lt;select id="queryUsersLikeUserName" resultType="User"&gt;
    	select &lt;include refid="CommonSQL.commonSql"&gt;&lt;/include&gt; from tb_user where user_name like "%"#{userName}"%"
    &lt;/select&gt;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    當然要完成這個功能還需要在全局配置文件mybatis-config.xml中引入該外部配置文件:

    <mappers>
    		<mapper resource="CommonSQL.xml"/>
    		<!-- 開啓mapper接口的包掃描,基於class的配置方式 -->
    		<package name="com.zpc.mybatis.mapper"/>
    </mappers>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    10.動態sql

    場景:查詢男性用戶,如果輸入了姓名,按姓名模糊查詢
    這裏寫圖片描述

    10.1.if

    場景:查詢男性用戶,如果輸入了姓名,則按姓名查詢

    定義接口:

    /**
     * 查詢男性用戶,如果輸入了姓名,則按姓名查詢
     * @param name
     * @return
     */
    List<User> queryUserList(@Param("name") String name);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    編寫mapper

    <select id="queryUserList" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user WHERE sex=1
        <if test="name!=null and name.trim()!=''">
          and name like '%${name}%'
        </if>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    測試

    @Test
    public void testqueryUserList() {
        List<User> users = this.userMapper.queryUserList(null);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    10.2.choose when otherwise

    場景:查詢男性用戶,如果輸入了姓名則按照姓名模糊查找,否則如果輸入了年齡則按照年齡查找,否則查找姓名爲“鵬程”的用戶。

    定義接口:

    /**
     * 查詢男性用戶,如果輸入了姓名則按照姓名模糊查找,否則如果輸入了年齡則按照年齡查找,否則查找姓名爲“鵬程”的用戶。
     * @param name
     * @param age
     * @return
     */
    List<User> queryUserListByNameOrAge(@Param("name") String name,@Param("age") Integer age);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    編寫mapper配置:

    <select id="queryUserListByNameOrAge" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user WHERE sex=1
        <!--
        1.一旦有條件成立的when,後續的when則不會執行
        2.當所有的when都不執行時,纔會執行otherwise
        -->
        <choose>
            <when test="name!=null and name.trim()!=''">
                and name like '%${name}%'
            </when>
            <when test="age!=null">
                and age = #{age}
            </when>
            <otherwise>
                and name='鵬程'
            </otherwise>
        </choose>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    測試:

    @Test
    public void queryUserListByNameOrAge() throws Exception {
        List<User> users = this.userMapper.queryUserListByNameOrAge(null, 16);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    10.3.where 和set

    場景一:查詢所有用戶,如果輸入了姓名按照姓名進行模糊查詢,如果輸入年齡,按照年齡進行查詢,如果兩者都輸入,兩個條件都要成立。

    接口:

    /**
     * 查詢所有用戶,如果輸入了姓名按照姓名進行模糊查詢,如果輸入年齡,按照年齡進行查詢,如果兩者都輸入,兩個條件都要成立
     * @param name
     * @param age
     * @return
     */
    List<User> queryUserListByNameAndAge(@Param("name") String name,@Param("age") Integer age);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    配置:

    <select id="queryUserListByNameAndAge" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user
        <!--如果多出一個and,會自動去除,如果缺少and或者多出多個and則會報錯-->
        <where>
            <if test="name!=null and name.trim()!=''">
                and name like '%${name}%'
            </if>
            <if test="age!=null">
                and age = #{age}
            </if>
        </where>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    測試:

    @Test
    public void queryUserListByNameAndAge() throws Exception {
        List<User> users = this.userMapper.queryUserListByNameAndAge("鵬程", 20);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    場景二:修改用戶信息,如果參數user中的某個屬性爲null,則不修改。
    接口:

    /**
     * 根據id更新用戶信息
     *
     * @param user
     */
    public void updateUser(User user);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    配置:

    <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User">
        UPDATE tb_user
        <trim prefix="set" suffixOverrides=",">
            <if test="userName!=null">user_name = #{userName},</if>
            <if test="password!=null">password = #{password},</if>
            <if test="name!=null">name = #{name},</if>
            <if test="age!=null">age = #{age},</if>
            <if test="sex!=null">sex = #{sex},</if>
            <if test="birthday!=null">birthday = #{birthday},</if>
            updated = now(),
        </trim>
        WHERE
        (id = #{id});
    </update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    測試:

    @Test
    public void testUpdateUser() {
        User user = new User();
        user.setBirthday(new Date());
        user.setName("靜靜");
        user.setPassword("123456");
        user.setSex(0);
        user.setUserName("Jinjin");
        user.setId("1");
        this.userMapper.updateUser(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    10.4.foreach

    場景:按照多個id查詢用戶信息

    接口:

    /**
     * 按多個Id查詢
     * @param ids
     * @return
     */
    List<User> queryUserListByIds(@Param("ids") String[] ids);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    配置:

    <select id="queryUserListByIds" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where id in
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    測試:

    @Test
    public void queryUserListByIds() throws Exception {
        List<User> users = this.userMapper.queryUserListByIds(new String[]{"1","2"});
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    If:testognl表達式或者簡單java代碼
    Choose when otherwise—>相當於if else if else
    When test參考if
    Where set 都有一定的糾錯功能
    Trim:prefix suffix prefixOverrides suffixOverrides
    Foreach:collection item saparator open close

    11.緩存

    11.1.一級緩存

    這裏寫圖片描述
    在mybatis中,一級緩存默認是開啓的,並且一直無法關閉

    一級緩存滿足條件:
    1、同一個session中
    2、相同的SQL和參數

    測試:

    @Test
    public void testQueryUserById() {
        System.out.println(this.userMapper.queryUserById("1"));
        System.out.println(this.userMapper.queryUserById("1"));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    2018-07-01 17:08:50,156 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
    2018-07-01 17:08:50,421 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057.
    2018-07-01 17:08:50,423 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
    2018-07-01 17:08:50,476 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
    2018-07-01 17:08:50,509 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
    User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
    User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用:sqlSession.clearCache();可以強制清除緩存

    測試:

    @Test
    public void testQueryUserById() {
        System.out.println(this.userMapper.queryUserById("1"));
        sqlSession.clearCache();
        System.out.println(this.userMapper.queryUserById("1"));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    日誌:

    2018-07-01 17:10:51,065 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
    2018-07-01 17:10:51,359 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057.
    2018-07-01 17:10:51,360 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
    2018-07-01 17:10:51,408 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
    2018-07-01 17:10:51,437 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
    User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
    2018-07-01 17:10:51,438 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
    2018-07-01 17:10:51,438 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
    2018-07-01 17:10:51,440 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
    User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    執行update、insert、delete的時候,會清空緩存
    測試:

    @Test
    public void testQueryUserById() {
        System.out.println(this.userMapper.queryUserById("1"));
        //sqlSession.clearCache();
    
    User user=new User();
    user.setName("美女");
    user.setId("1");
    userMapper.updateUser(user);
    
    System.out.println(this.userMapper.queryUserById("1"));
    

    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    日誌:

    2018-07-01 17:18:15,128 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
    2018-07-01 17:18:15,399 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057.
    2018-07-01 17:18:15,401 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
    2018-07-01 17:18:15,466 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
    2018-07-01 17:18:15,492 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
    User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
    2018-07-01 17:18:15,527 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] ==>  Preparing: UPDATE tb_user set name = ?, updated = now() WHERE (id = ?); 
    2018-07-01 17:18:15,529 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] ==> Parameters: 美女(String), 1(String)
    2018-07-01 17:18:15,532 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] <==    Updates: 1
    2018-07-01 17:18:15,532 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
    2018-07-01 17:18:15,533 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
    2018-07-01 17:18:15,538 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
    User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    11.2.二級緩存

    mybatis 的二級緩存的作用域是一個mapper的namespace ,同一個namespace中查詢sql可以從緩存中命中。

    開啓二級緩存:

    <mapper namespace="com.zpc.mybatis.dao.UserMapper">
        <cache/>
    </mapper>
    
    • 1
    • 2
    • 3

    測試:

    @Test
    public void testCache() {
        System.out.println(this.userMapper.queryUserById("1"));
    
    sqlSession.close();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
    System.out.println(mapper.queryUserById("1"));
    

    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    開啓二級緩存,必須序列化:

    public class User implements Serializable{
        private static final long serialVersionUID = -3330851033429007657L;
    
    • 1
    • 2

    日誌:

    2018-07-01 17:23:39,335 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
    2018-07-01 17:23:39,664 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 2092769598.
    2018-07-01 17:23:39,665 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
    2018-07-01 17:23:39,712 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
    2018-07-01 17:23:39,734 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
    User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}
    2018-07-01 17:23:39,743 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7cbd213e]
    2018-07-01 17:23:39,744 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 2092769598 to pool.
    2018-07-01 17:23:39,746 [main] [com.zpc.mybatis.dao.UserMapper]-[DEBUG] Cache Hit Ratio [com.zpc.mybatis.dao.UserMapper]: 0.5
    User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    關閉二級緩存:
    不開啓,或者在全局的mybatis-config.xml 中去關閉二級緩存
    這裏寫圖片描述

    <settings>
        <!--開啓駝峯匹配-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--開啓二級緩存,全局總開關,這裏關閉,mapper中開啓了也沒用-->
        <setting name="cacheEnabled" value="false"/>
    </settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    這裏寫圖片描述

    12.高級查詢

    12.1.表關係說明

    這裏寫圖片描述
    創建order表:
    CREATE TABLE tb_order (
    id int(11) NOT NULL AUTO_INCREMENT,
    user_id int(11) DEFAULT NULL,
    order_number varchar(255) DEFAULT NULL,
    create datetime DEFAULT NULL,
    updated datetime DEFAULT NULL,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

    public class Order {
        private Integer id;
        private Long userId;
        private String orderNumber;
        private Date created;
        private Date updated;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    需求說明:
    這裏寫圖片描述

    12.2.一對一查詢

    方法一:核心思想擴展Order對象,來完成映射
    新建OrderUser實體類繼承Order:

    public class OrderUser extends Order {
        private String userName;
        private String password;
        private String name;
        private Integer age;
        private Integer sex;
        private Date birthday;
        private Date created;
        private Date updated;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    OrderMapper接口:

    public interface OrderMapper {
         OrderUser queryOrderUserByOrderNumber(@Param("number") String number);
    }
    
    • 1
    • 2
    • 3

    配置OrderMapper:

     <mapper namespace="com.zpc.mybatis.dao.OrderMapper">
        <select id="queryOrderUserByOrderNumber" resultType="com.zpc.mybatis.pojo.OrderUser">
          select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number}
       </select>
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    測試:

    @Test
    public void queryOrderUserByOrderNumber() throws Exception {
        OrderUser orderUser = orderMapper.queryOrderUserByOrderNumber("201807010001");
        System.out.println(orderUser);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    方法二:面向對象的思想,在Order對象中添加User對象。

    在Order對象中添加User屬性:

    public class Order {
        private Integer id;
        private Long userId;
        private String orderNumber;
        private Date created;
        private Date updated;
        private User user;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    接口:

    /**
     * 根據訂單號查詢訂單用戶的信息
     * @param number
     * @return
     */
    Order queryOrderWithUserByOrderNumber(@Param("number") String number);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用resultType不能完成自動映射,需要手動完成結果集映射resultMap:

     <resultMap id="OrderUserResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
         <id column="id" property="id"/>
         <!--association:完成子對象的映射-->
         <!--property:子對象在父對象中的屬性名-->
         <!--javaType:子對象的java類型-->
         <!--autoMapping:完成子對象的自動映射,若開啓駝峯,則按駝峯匹配-->
         <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
             <id column="user_id" property="id"/>
         </association>
     </resultMap>
    

    <select id=“queryOrderWithUserByOrderNumber” resultMap=“OrderUserResultMap”>
    select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number}
    </select>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    測試:

    @Test
    public void queryOrderWithUserByOrderNumber() throws Exception {
        Order order = orderMapper.queryOrderWithUserByOrderNumber("201807010001");
        System.out.println(order.getUser());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    12.3.一對多查詢

    一對多查詢:查詢訂單,查詢出下單人信息並且查詢出訂單詳情。

    Order類:

    public class Order {
        private Integer id;
        private Long userId;
        private String orderNumber;
        private Date created;
        private Date updated;
        private User user;
        private List<OrderDetail> detailList;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    public class OrderDetail {
        private Integer id;
        private Integer orderId;
        private Double totalPrice;
        private Integer status;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    接口:

    /**
     * 根據訂單號查詢訂單用戶的信息及訂單詳情
     * @param number
     * @return
     */
    Order queryOrderWithUserAndDetailByOrderNumber(@Param("number") String number);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Mapper映射:

    <resultMap id="OrderUserDetailResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
        <id column="id" property="id"/>
        <!--collection:定義子對象集合映射-->
        <!--association:完成子對象的映射-->
        <!--property:子對象在父對象中的屬性名-->
        <!--javaType:子對象的java類型-->
        <!--autoMapping:完成子對象的自動映射,若開啓駝峯,則按駝峯匹配-->
        <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
            <id column="user_id" property="id"/>
        </association>
        <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true">
            <id column="id" property="id"/>
        </collection>
    </resultMap>
    

    <select id=“queryOrderWithUserAndDetailByOrderNumber” resultMap=“OrderUserDetailResultMap”>
    select * from tb_order o
    left join tb_user u on o.user_id=u.id
    left join tb_orderdetail od on o.id=od.order_id
    where o.order_number = #{number}
    </select>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    測試:

    @Test
    public void queryOrderWithUserAndDetailByOrderNumber() throws Exception {
        Order order = orderMapper.queryOrderWithUserAndDetailByOrderNumber("201807010001");
        System.out.println(order.getUser());
        System.out.println(order.getDetailList());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    12.4.多對多查詢

    多對多查詢:查詢訂單,查詢出下單人信息並且查詢出訂單詳情中的商品數據。

    OrderDetail類

    public class OrderDetail {
        private Integer id;
        private Integer orderId;
        private Double totalPrice;
        private Integer status;
        private Item item;
    }
    

    public class Item {
    private Integer id;
    private String itemName;
    private Float itemPrice;
    private String itemDetail;
    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    接口:

    /**
     * 根據訂單號查詢訂單用戶的信息及訂單詳情及訂單詳情對應的商品信息
     * @param number
     * @return
     */
    Order queryOrderWithUserAndDetailItemByOrderNumber(@Param("number") String number);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Mapper配置:

    <resultMap id="OrderUserDetailItemResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
        <id column="id" property="id"/>
        <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
            <id column="user_id" property="id"/>
        </association>
        <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true">
            <id column="detail_id" property="id"/>
            <association property="item" javaType="com.zpc.mybatis.pojo.Item" autoMapping="true">
                <id column="item_id" property="id"/>
            </association>
        </collection>
    </resultMap>
    

    <select id=“queryOrderWithUserAndDetailItemByOrderNumber” resultMap=“OrderUserDetailItemResultMap”>
    select * ,od.id as detail_id from tb_order o
    left join tb_user u on o.user_id=u.id
    left join tb_orderdetail od on o.id=od.order_id
    left join tb_item i on od.item_id=i.id
    where o.order_number = #{number}
    </select>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    測試:

    @Test
    public void queryOrderWithUserAndDetailItemByOrderNumber() throws Exception {
        Order order = orderMapper.queryOrderWithUserAndDetailItemByOrderNumber("201807010001");
        System.out.println(order);
        System.out.println(order.getUser());
        System.out.println(order.getDetailList());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    至此,目錄結構如下:
    這裏寫圖片描述
    數據庫腳本:
    CREATE TABLE tb_order (
    id int(11) NOT NULL AUTO_INCREMENT,
    user_id int(11) DEFAULT NULL,
    order_number varchar(255) DEFAULT NULL,
    create datetime DEFAULT NULL,
    updated datetime DEFAULT NULL,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
    INSERT INTO tb_order VALUES (‘1’, ‘2’, ‘201807010001’, ‘2018-07-01 19:38:35’, ‘2018-07-01 19:38:40’);

    CREATE TABLE tb_item (
    id int(11) NOT NULL,
    itemName varchar(255) DEFAULT NULL,
    itemPrice decimal(10,2) DEFAULT NULL,
    itemDetail varchar(255) DEFAULT NULL,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    INSERT INTO tb_item VALUES (‘1’, ‘襪子’, ‘29.90’, ‘香香的襪子’);
    INSERT INTO tb_item VALUES (‘2’, ‘套子’, ‘99.99’, ‘岡本001’);

    CREATE TABLE tb_orderdetail (
    id int(11) NOT NULL AUTO_INCREMENT,
    order_id int(11) DEFAULT NULL,
    total_price decimal(10,0) DEFAULT NULL,
    item_id int(11) DEFAULT NULL,
    status int(10) unsigned zerofill DEFAULT NULL COMMENT ‘0成功非0失敗’,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    INSERT INTO tb_orderdetail VALUES (‘1’, ‘1’, ‘10000’, ‘1’, ‘0000000001’);
    INSERT INTO tb_orderdetail VALUES (‘2’, ‘1’, ‘2000’, ‘2’, ‘0000000000’);

    12.5.resultMap的繼承

    這裏寫圖片描述

    12.6.高級查詢的整理

    resutlType無法幫助我們自動的去完成映射,所以只有使用resultMap手動的進行映射
    type 結果集對應的數據類型 id 唯一標識,被引用的時候,進行指定

    <resultMap type="Order" id="orderUserLazyResultMap">
    <!—定義pojo中的單個對象的 property 定義對象的屬性名, javaType 屬性的類型,
    		<association property="user" javaType="User" autoMapping="true">
    			<id />
    		</association>
    <!—如果屬性是集合使用collection ,javaType 集合的類型,ofType 表示集中的存儲的元素類型
    		<collection property="details" javaType="List" ofType="OrderDetail" autoMapping="true">
    			<id />
    </resultMap>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    13.延遲加載

    這裏寫圖片描述
    這裏寫圖片描述
    編寫接口:
    這裏寫圖片描述
    Mapper配置:
    這裏寫圖片描述
    測試:
    這裏寫圖片描述
    結果:
    這裏寫圖片描述

    開啓延遲加載:
    這裏寫圖片描述
    修改測試用例:
    這裏寫圖片描述
    執行,報錯:
    這裏寫圖片描述
    添加cglib:

    <dependency>
    		<groupId>cglib</groupId>
    		<artifactId>cglib</artifactId>
    		<version>3.1</version>
    	</dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    執行:
    這裏寫圖片描述

    14.如果sql語句中出現’<’的解決方案

    1、使用xml中的字符實體

    這裏寫圖片描述
    因爲業務,需要在mybatis中,使用到大於號,小於號,所以就在SQL中直接使用了。
    SELECT * FROM test WHERE 1 = 1 AND start_date <= CURRENT_DATE AND end_date >= CURRENT_DATE
    可是,在執行時,總報錯誤:
    ```Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 74; columnNumber: 17; ``元素內容必須由格式正確的字符數據或標記組成。
    把AND start_date >= CURRENT_DATE AND end_date <= CURRENT_DATE去掉,就沒有問題,所以確定是因爲大於號,小於號引起的問題。

    於是就想到了特殊符號,於是用了轉義字符把>和<替換掉,然後就沒有問題了。
    SELECT * FROM test WHERE 1 = 1 AND start_date &lt;= CURRENT_DATE AND end_date &gt;= CURRENT_DATE
    案例:

    1.<if test="startDateTime!=null"> and mm.ttime &gt; to_date(#{startDateTime},'yyyy-mm-dd hh24:mi:ss')</if>  
    2.<if test="endDateTime!=null"> and mm.ttime &lt;= to_date(#{endDateTime},'yyyy-mm-dd hh24:mi:ss')</if>  
    
    • 1
    • 2

    2、使用<![CDATA[ < ]]>

    案例1:

    1.<![CDATA[ 
    2.       and mm.ttime > to_date(#{startDateTime},'yyyy-mm-dd hh24:mi:ss') 
    3.       and mm.ttime <= to_date(#{endDateTime},'yyyy-mm-dd hh24:mi:ss') 
    4.]]>  
    
    • 1
    • 2
    • 3
    • 4

    案例2:

    mapper文件示例代碼 :

    and (t1.status <![CDATA[ >= ]]> 1  and  t1.status <![CDATA[ <= ]]> 2)
    上述代碼其實對應的sql:
    and (t1.status > =1 andt1.status <= 2)
    
    • 1
    • 2
    • 3

    注意:

    使用<![CDATA[ ]]>標記的sql語句中的<where> <if>等標籤不會被解析。
    
    • 1

    15.Spring 集成Mybatis

    15.1引入spring和Mybatis相關依賴

    pom.xml

    <!--數據庫連接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.8</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.2.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>4.1.3.RELEASE</version>
    </dependency>
    <!--spring集成Junit測試-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>4.1.3.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <!--spring容器-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.1.3.RELEASE</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    15.2配置spring配置文件

    applicationContext-dao.xml

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
    &lt;!-- 加載配置文件 --&gt;
    &lt;context:property-placeholder location="classpath:properties/*.properties"/&gt;
    &lt;!-- 數據庫連接池 --&gt;
    &lt;bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close"&gt;
        &lt;property name="driverClassName" value="${jdbc.driver}"/&gt;
        &lt;property name="url"
                  value="jdbc:mysql://${jdbc.host}:3306/${jdbc.database}?useUnicode=true&amp;amp;characterEncoding=utf-8&amp;amp;zeroDateTimeBehavior=convertToNull"/&gt;
        &lt;property name="username" value="${jdbc.userName}"/&gt;
        &lt;property name="password" value="${jdbc.passWord}"/&gt;
        &lt;!-- 初始化連接大小 --&gt;
        &lt;property name="initialSize" value="${jdbc.initialSize}"&gt;&lt;/property&gt;
        &lt;!-- 連接池最大數據庫連接數  0 爲沒有限制 --&gt;
        &lt;property name="maxActive" value="${jdbc.maxActive}"&gt;&lt;/property&gt;
        &lt;!-- 連接池最大的空閒連接數,這裏取值爲20,表示即使沒有數據庫連接時依然可以保持20空閒的連接,而不被清除,隨時處於待命狀態 0 爲沒有限制 --&gt;
        &lt;property name="maxIdle" value="${jdbc.maxIdle}"&gt;&lt;/property&gt;
        &lt;!-- 連接池最小空閒 --&gt;
        &lt;property name="minIdle" value="${jdbc.minIdle}"&gt;&lt;/property&gt;
        &lt;!--最大建立連接等待時間。如果超過此時間將接到異常。設爲-1表示無限制--&gt;
        &lt;property name="maxWait" value="${jdbc.maxWait}"&gt;&lt;/property&gt;
    &lt;/bean&gt;
    
    &lt;!-- spring和MyBatis完美整合 --&gt;
    &lt;bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"&gt;
        &lt;property name="dataSource" ref="dataSource"/&gt;
        &lt;!-- 自動掃描mapping.xml文件 --&gt;
        &lt;property name="mapperLocations" value="classpath:mappers/*.xml"&gt;&lt;/property&gt;
        &lt;!--如果mybatis-config.xml沒有特殊配置也可以不需要下面的配置--&gt;
        &lt;property name="configLocation" value="classpath:mybatis-config.xml" /&gt;
    &lt;/bean&gt;
    
    &lt;!-- DAO接口所在包名,Spring會自動查找其下的類 --&gt;
    &lt;bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"&gt;
        &lt;property name="basePackage" value="com.zpc.mybatis.dao"/&gt;
        &lt;property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"&gt;&lt;/property&gt;
    &lt;/bean&gt;
    
    &lt;!-- (事務管理)transaction manager --&gt;
    &lt;bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
        &lt;property name="dataSource" ref="dataSource"/&gt;
    &lt;/bean&gt;
    

    </beans>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    db.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.host=localhost
    jdbc.database=ssmdemo
    jdbc.userName=root
    jdbc.passWord=123456
    jdbc.initialSize=0
    jdbc.maxActive=20
    jdbc.maxIdle=20
    jdbc.minIdle=1
    jdbc.maxWait=1000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    由於applicationContext-dao.xml中配置了Mapper接口掃描,所以刪除mybatis-config.xml中的配置,否則報已映射錯誤:
    Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for MyMapper.selectUser
    刪除mybatis-config.xml中的映射配置:

    <!--<mappers>-->
        <!--<mapper resource="mappers/MyMapper.xml"/>-->
        <!--<mapper resource="mappers/UserDaoMapper.xml"/>-->
        <!--<mapper resource="mappers/UserMapper.xml"/>-->
        <!--<mapper resource="mappers/OrderMapper.xml"/>-->
    <!--</mappers>-->
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    或者在構建sqlSessionFactory時不配置mybatis-config.xml也行:

    <!-- spring和MyBatis完美整合 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 自動掃描mapping.xml文件 -->
        <property name="mapperLocations" value="classpath:mappers/*.xml"></property>
        <!--如果mybatis-config.xml沒有特殊配置也可以不需要下面的配置-->
        <!--<property name="configLocation" value="classpath:mybatis-config.xml" />-->
    </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    15.3 測試

    UserMapperSpringTest.java

    import com.zpc.mybatis.dao.UserMapper;
    import com.zpc.mybatis.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import java.io.InputStream;
    import java.util.Date;
    import java.util.List;
    

    //目標:測試一下spring的bean的某些功能
    @RunWith(SpringJUnit4ClassRunner.class)//junit整合spring的測試//立馬開啓了spring的註解
    @ContextConfiguration(locations=“classpath:spring/applicationContext-*.xml”)//加載核心配置文件,自動構建spring容器
    public class UserMapperSpringTest {

    @Autowired
    private UserMapper userMapper;
    
    @Test
    public void testQueryUserByTableName() {
        List&lt;User&gt; userList = this.userMapper.queryUserByTableName("tb_user");
        for (User user : userList) {
            System.out.println(user);
        }
    }
    
    @Test
    public void testLogin() {
        System.out.println(this.userMapper.login("hj", "123456"));
    }
    
    @Test
    public void testQueryUserById() {
        System.out.println(this.userMapper.queryUserById("1"));
        User user = new User();
        user.setName("美女");
        user.setId("1");
        userMapper.updateUser(user);
    
        System.out.println(this.userMapper.queryUserById("1"));
    }
    
    @Test
    public void testQueryUserAll() {
        List&lt;User&gt; userList = this.userMapper.queryUserAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }
    
    @Test
    public void testInsertUser() {
        User user = new User();
        user.setAge(20);
        user.setBirthday(new Date());
        user.setName("大神");
        user.setPassword("123456");
        user.setSex(2);
        user.setUserName("bigGod222");
        this.userMapper.insertUser(user);
        System.out.println(user.getId());
    }
    
    @Test
    public void testUpdateUser() {
        User user = new User();
        user.setBirthday(new Date());
        user.setName("靜靜");
        user.setPassword("123456");
        user.setSex(0);
        user.setUserName("Jinjin");
        user.setId("1");
        this.userMapper.updateUser(user);
    }
    
    @Test
    public void testDeleteUserById() {
        this.userMapper.deleteUserById("1");
    }
    
    @Test
    public void testqueryUserList() {
        List&lt;User&gt; users = this.userMapper.queryUserList(null);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    @Test
    public void queryUserListByNameAndAge() throws Exception {
        List&lt;User&gt; users = this.userMapper.queryUserListByNameAndAge("鵬程", 20);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    @Test
    public void queryUserListByNameOrAge() throws Exception {
        List&lt;User&gt; users = this.userMapper.queryUserListByNameOrAge(null, 16);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    @Test
    public void queryUserListByIds() throws Exception {
        List&lt;User&gt; users = this.userMapper.queryUserListByIds(new String[]{"5", "2"});
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章