1. 程式人生 > 其它 >測試開發進階——spring boot——MVC——MyBatis初步瞭解(轉載)

測試開發進階——spring boot——MVC——MyBatis初步瞭解(轉載)

Mybatis介紹#

​ MyBatis 本是apache的一個開源專案iBatis, 2010年這個專案由apache software foundation 遷移到了google code,並且改名為MyBatis 。

2013年11月遷移到Github。MyBatis是一個優秀的持久層框架,它對jdbc的操作資料庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設定引數、結果集檢索等jdbc繁雜的過程程式碼。Mybatis通過xml或註解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,並通過java物件和statement中的sql進行對映生成最終執行的sql語句,最後由mybatis框架執行sql並將結果對映成java物件並返回。

Mybatis框架#

框架介紹

1、 mybatis配置

SqlMapConfig.xml,此檔案作為mybatis的全域性配置檔案,配置了mybatis的執行環境等資訊。

mapper.xml檔案即sql對映檔案,檔案中配置了操作資料庫的sql語句。此檔案需要在SqlMapConfig.xml中載入。

2、 通過mybatis環境等配置資訊構造SqlSessionFactory即會話工廠

3、 由會話工廠建立sqlSession即會話,操作資料庫需要通過sqlSession進行。

4、 mybatis底層自定義了Executor執行器介面操作資料庫,Executor介面有兩個實現,一個是基本執行器、一個是快取執行器。

5、 Mapped Statement也是mybatis一個底層封裝物件,它包裝了mybatis配置資訊及sql對映資訊等。mapper.xml檔案中一個sql對應一個Mapped Statement物件,sql的id即是Mapped statement的id。

6、 Mapped Statement對sql執行輸入引數進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql前將輸入的java物件對映至sql中,輸入引數對映就是jdbc程式設計中對preparedStatement設定引數。

7、 Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql後將輸出結果對映至java物件中,輸出結果對映過程相當於jdbc程式設計中對結果的解析處理過程。

利用IDEA建立Mybatis的入門案例#

8個步驟#

  1. 建立maven工程,什麼都不選就ok,並匯入座標;
Copy
<packaging>jar</packaging>
<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.12</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.10</version>
    </dependency>
</dependencies>
  1. 編寫User實體類
Copy
public class User implements Serializable {
    private int id;
    private String username;// 使用者姓名
    private String sex;// 性別
    private Date birthday;// 生日
    private String address;// 地址

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex
                + ", birthday=" + birthday + ", address=" + address + "]";
    }

}
  1. 在resources資料夾中,建立Mybatis的主配置檔案SqlMapConfig.xml。它是mybatis核

    心配置檔案,配置檔案內容為資料來源、事務管理。

    配置環境:

    • 配置mysql的環境:
    1. 配置事務的型別;
    2. 配置連線池:配置連線資料庫的4個基本資訊;
    • 指定對映配置檔案的位置:

程式碼如下:

Copy
<?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>
<!--   配置環境-->
    <environments default="mysql">
 	    <!--配置mysql的環境-->
        <environment id="mysql">
  		   <!--配置事務的型別-->
            <transactionManager type="JDBC"></transactionManager>
		   <!--配置連線池-->
            <dataSource type="POOLED">
				<!--配置連線資料庫的4個基本資訊-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.214.128:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="ben123"/>
            </dataSource>
        </environment>
    </environments>

<!--指定對映配置檔案的位置,對映配置檔案指的是每個dao獨立的配置檔案-->
    <mappers>
        <mapper resource="com/ben/dao/IUserDao.xml"/>
    </mappers>
</configuration>
  1. 在resources資料夾中匯入log4j.properties檔案
Copy
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
  1. 編寫對映檔案 IUserDao.xml ,位置在目錄resource->sqlmap->User.xml
Copy
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:名稱空間,用於隔離sql,還有一個很重要的作用,後面會講 -->
<mapper namespace="test">
</mapper>
  1. 載入對映檔案,將User.xml新增在SqlMapConfig.xml下
Copy
<!--指定對映配置檔案的位置-->
<mappers>
    <mapper resource="sqlmao/User.xml"/>
</mappers>
  1. 編寫測試類:在test->java目錄下建立測試類com.ben.test.MybatisTest。實現業務需求,共7步,其中2,3步可以合在一起。
Copy
1. 載入核心配置檔案SqlMapConfig.xml
2. 建立SqlSessionFactoryBuilder物件
3. 建立SqlSessionFactory物件(2,3可以寫一起)
4. 建立SqlSession物件
5. 執行SqlSession物件執行查詢,獲取結果User
6. 列印結果
7. 釋放資源

程式碼如下:

Copy
package com.ben.test;

import com.ben.domain.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.Test;

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

/**
 * @ClassName: MybatisTest
 * @author: benjamin
 * @version: 1.0
 * @description: TODO
 * @createTime: 2019/07/13/11:50
 */

public class MybatisTest {
    public static void main(String[] args) {


    }
    //通過Id查詢一個使用者
    @Test
    public void testSearchById() throws IOException {
        //1.讀取配置檔案
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.建立SqlSessionFactory工廠
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //3.使用工廠生產SqlSession物件
        SqlSession session = sqlSessionFactory.openSession();
        //4.執行Sql語句
        User user = session.selectOne("test.findUserById", 10);
        //5. 列印結果
        System.out.println(user);
        //6.釋放資源
        session.close();
        in.close();
    }

    //根據使用者名稱模糊查詢使用者列表
    @Test
    public void testFindUserByUsername() throws IOException {
        //1.讀取配置檔案
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.建立SqlSessionFactory工廠
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //3.使用工廠生產SqlSession物件
        SqlSession session = sqlSessionFactory.openSession();
        //4.執行Sql語句
        List<User> list = session.selectList("test.findUserByUsername", "王");
        //5. 列印結果
        for (User user:list) {
            System.out.println(user);
        }
        //6.釋放資源
        session.close();
        in.close();
    }

    //新增使用者
    @Test
    public void testInsertUser() throws IOException {
        //1.讀取配置檔案
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.建立SqlSessionFactory工廠
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //3.使用工廠生產SqlSession物件
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4.執行Sql語句
        User user = new User();
        user.setUsername("小強");
        user.setBirthday(new Date());
        user.setAddress("sadfsafsafs");
        user.setSex("2");
        int i = sqlSession.insert("test.insertUser", user);
        sqlSession.commit();
        //5. 列印結果
        // 剛儲存使用者,此時使用者ID需要返回。執行完上面insert程式後,此時就能知道使用者的ID是多少
        // 需要在User.xml檔案中配置
        System.out.println("插入id:"+user.getId());//插入id:30

        //6.釋放資源
        sqlSession.close();
        in.close();
    }
    //更新使用者
    @Test
    public void testUpdateUserById() throws IOException {
        //1.讀取配置檔案
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.建立SqlSessionFactory工廠
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //3.使用工廠生產SqlSession物件
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4.執行Sql語句
        User user = new User();
        user.setId(27);
        user.setUsername("小小");
        user.setBirthday(new Date());
        user.setAddress("西安市");
        user.setSex("1");
        int i = sqlSession.insert("test.updateUserById", user);
        sqlSession.commit();
        //5. 列印結果
        System.out.println(user.getId());
        //6.釋放資源
        sqlSession.close();
        in.close();
    }
    //刪除使用者
    @Test
    public void testDeleteUserById() throws IOException {
        //1.讀取配置檔案
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.建立SqlSessionFactory工廠
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //3.使用工廠生產SqlSession物件
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4.執行Sql語句
        int i = sqlSession.insert("test.deleteUserById", 32);
        sqlSession.commit();
        //5. 列印結果
        System.out.println(i);
        //6.釋放資源
        sqlSession.close();
        in.close();
    }
}
  1. 配置對映配置檔案User.xml
Copy
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:用來區別不同的類的名字 -->
<mapper namespace="test">

    <!-- 通過Id查詢一個使用者   -->
    <select id="findUserById" parameterType="Integer" resultType="com.ben.domain.User">
        select * from user where id = #{v}
    </select>

    <!-- 根據使用者名稱模糊查詢使用者列表 -->
    <!--    select * from user where username like '%${value}%'-->
<!-- select * from user where username like "%"#{value}"%"-->
    <select id="findUserByUsername" parameterType="String" resultType="com.ben.domain.User">
        select * from user where username like #{username}
    </select>
    <!--  新增使用者  -->
    <insert id="insertUser" parameterType="com.ben.domain.User">
        <selectKey keyProperty="id" resultType="Integer" order="AFTER">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user (username,birthday,address,sex) values(#{username},#{birthday},#{address},#{sex})
    </insert>
    <!-- 更新使用者 -->
    <update id="updateUserById" parameterType="com.ben.domain.User">
		update user
		set username = #{username},sex = #{sex},birthday = #{birthday},address = #{address}
		where id = #{id}
	</update>
    <!-- 刪除使用者   -->
    <delete id="deleteUserById" parameterType="Integer">
		delete from user
		where id = #{vvvvv}
	</delete>
</mapper>

注意事項#

詳解引數#

Copy
namespace:用來區別不同的類的名字 
id:標識對映檔案中的sql,稱為statement的id將sql語句封裝到mappedStatement物件中,所以將id稱為statement的id
parameterType:指定輸入引數的型別.
resultType:指定輸出結果型別。mybatis將sql查詢結果的一行記錄資料對映為resultType指定型別的物件。如果有多條資料,則分別進行對映,並把物件放到容器List中
Copy
#{}:一個佔位符。preparedStatement向佔位符中設定值,自動進行java型別和jdbc型別轉換。#{}可以有效防止sql注入。 #{}可以接收簡單型別值或pojo屬性值。 如果parameterType傳輸單個簡單型別值,#{}括號中可以是value或其它名稱。

${}:表示拼接sql串,通過${}可以將parameterType 傳入的內容拼接在sql中且不進行jdbc型別轉換,${}可以接收簡單型別值或pojo屬性值,如果parameterType傳輸單個簡單型別值,${}括號中只能是value。

解釋select語句#

這一部分參考mybatis官網。詳情點選http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

Copy
<select id="findUserById" parameterType="Integer" resultType="com.ben.domain.User">
    select * from user where id = #{v}
</select>

這個語句被稱作findUserById, 接受一個Integer型別的引數,返回一個User物件。#{V} 告訴mybatis建立一個預處理語句引數,在JDBC中,這個的一個引數在Sql中會由一個“ ?”表示,並被傳遞到新的預處理語句中,如:

Copy
//近似的JDBC程式碼,並非Mybatis程式碼
String findUserById = "select * from user where id = ?";
PreparedStatement ps = conn.prepareStatement(findUserById);
ps.setInt(1,id);

使用 JDBC 意味著需要更多的程式碼來提取結果並將它們對映到物件例項中,而這就是 MyBatis 節省你時間的地方.

注意#

  • 在根據使用者名稱模糊查詢中注意:有兩種寫法。
Copy
1.測試類中這樣寫:
List<User> list = session.selectList("test.findUserByUsername", "王");
在User.xml中寫:
select * from user where username like '%${value}%'
其對應的實際sql操作語句:select * from user where username like'%五%'
也可以這樣寫:
select * from user where username like "%"#{value}"%" # value 可以換成haha
其對應的sql查詢語句是:select * from user where username like"%"'五'"%"
2.如果測試類中這樣寫:
List<User> list = session.selectList("test.findUserByUsername", "%王%");
User.xml這樣寫
select * from user where username like #{username} 
其中username可以換成haha等其他名稱。
  • 執行插入操作時,儲存成功,但是id=0,需要解決id返回不正常的問題。如果剛儲存使用者,此時使用者ID需要返回。執行完上面insert程式後,此時就能知道使用者的ID是多少,需要在插入之前補充語句:
Copy
<selectKey keyProperty="id" resultType="Integer" order="AFTER">
    select LAST_INSERT_ID()
</selectKey>