MyBatis快速入門

環(huán)境準(zhǔn)備

  • 數(shù)據(jù)庫
    示例使用的使用MySQL8數(shù)據(jù)庫,創(chuàng)建一個(gè)用戶表user,包括以下兩個(gè)字段,一個(gè)是主鍵id,一個(gè)是用戶名username
列名 數(shù)據(jù)類型 其它
id int(11) auto_increment
username varchar(32)
  • 開發(fā)工具
    示例使用的是Eclipse 2019-09
  • 其它
    可以使用Eclipse內(nèi)置的Maven3,也可以使用自行安裝的Maven。使用自行安裝的Maven,配置好Eclipse即可。

一個(gè)簡單實(shí)例

這個(gè)是比較傳統(tǒng)和普遍的做法,對于數(shù)據(jù)庫的API操作,按照分層習(xí)慣,會封裝在DAO里面。編碼的核心是聲明一個(gè)DAO接口,然后在DAO接口的實(shí)現(xiàn)類中調(diào)用MyBatis的API,從而實(shí)現(xiàn)對MyBatis的集成。而相關(guān)的所有SQL語句,則寫在xml格式的SQL映射文件中。

業(yè)務(wù)需求

一個(gè)簡單的用戶查詢?yōu)槔?,從MySQL數(shù)據(jù)庫中根據(jù)用戶id查詢用戶信息。

編碼流程

主要分成以下步驟

  • 創(chuàng)建全局配置文件
    全局配置文件的名字可以隨意,比如mybatis-config.xml。在全局配置文件中,可以配置數(shù)據(jù)庫連接、插件(如分頁插件)、SQL映射文件資源路徑等信息。對于數(shù)據(jù)庫連接,習(xí)慣做法會另外創(chuàng)建一個(gè)db.properties屬性文件單獨(dú)保存數(shù)據(jù)庫連接信息,然后在mybatis-config.xml文件中去引用。
  • 創(chuàng)建數(shù)據(jù)表POJO對象
    POJO對象主要用來傳遞語句的參數(shù)值,以及保存執(zhí)行SQL語句后數(shù)據(jù)庫返回給程序的操作結(jié)果。大多數(shù)情況下,POJO對象中的屬性名會與數(shù)據(jù)表列名一一對應(yīng)(也可以手動(dòng)屬性名和列名的映射關(guān)系)。比如可以創(chuàng)建User.java對應(yīng)user表。
  • 創(chuàng)建數(shù)據(jù)表SQL映射文件
    比如對用戶表user的相關(guān)SQL,可以創(chuàng)建一個(gè)UserMapper.xml來保存對用戶表的SQL語句。
  • 創(chuàng)建DAO接口及其實(shí)現(xiàn)類
    DAO接口聲明對數(shù)據(jù)庫的操作方法,在實(shí)現(xiàn)類中調(diào)用MyBatis的API實(shí)現(xiàn)對數(shù)據(jù)庫的操作。比如對user的操作,可以創(chuàng)建UserDao.java接口和UserDaoImpl.java實(shí)現(xiàn)類。

創(chuàng)建Maven工程

使用Eclipse創(chuàng)建一個(gè)Maven工程,編碼完成后,項(xiàng)目結(jié)構(gòu)大概如下


項(xiàng)目工程目錄結(jié)構(gòu)

其中pom.xml文件內(nèi)容如下,主要是引入了mybatis、mysql以及junit依賴

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.fandou.mybatis</groupId>
    <artifactId>mybatis-beginning</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.17</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId> 
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

實(shí)例代碼

按照上面的編碼流程,按順序先后創(chuàng)建的文件清單如下

  • mybatis-config.xml
  • db.properties
  • User.java
  • UserMapper.xml
  • UserDao.java
  • UserDaoImpl.java
  • Test01.java //測試類

各個(gè)文件的具體代碼分別如下
1、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>
<!-- 加載db.properties屬性文件 -->
<properties resource="db.properties"></properties>

<!-- 定義環(huán)境,默認(rèn)使用development -->
  <environments default="development">
  
  <!-- 定義環(huán)境development,配置對應(yīng)的JDBC數(shù)據(jù)庫連接,相關(guān)的連接信息在db.properties屬性文件中定義 -->
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
    
  </environments>
  <mappers>
    <mapper resource="com/fandou/mybatis/beginning/demo01/mapper/UserMapper.xml"/>
  </mappers>
</configuration>

2、db.properties

#//這里的屬性名與mybatis-config.xml文件中的保持一致
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.101.28:3306/vhr?characterEncoding=utf8
jdbc.username=sqcheng
jdbc.password=123456

3、User.java

package com.fandou.mybatis.beginning.demo01.po;

import java.io.Serializable;

public class User implements Serializable {

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = -5944097591296647171L;
    
    private int id;
    private String username;
    
    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;
    }

}

4、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">
<!-- 注意這里的namespace,目前隨意命名即可 -->
<mapper namespace="UserMapper">
  <select id="findById" resultType="com.fandou.mybatis.beginning.demo01.po.User">
    select * from user where id = #{id}
  </select>
</mapper>

5、UserDao.java

package com.fandou.mybatis.beginning.demo01.dao;

import com.fandou.mybatis.beginning.demo01.po.User;

public interface UserDao {
    /**
     * 根據(jù)用戶id查詢用戶信息
     * @param id
     * @return
     */
    User findById(int id);
}

6、UserDaoImpl.java

package com.fandou.mybatis.beginning.demo01.dao;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.fandou.mybatis.beginning.demo01.po.User;

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory sqlSessionFactory;

    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @Override
    public User findById(int id) {
        SqlSession session = null;
        User user = null;
        try {
            session = sqlSessionFactory.openSession();
            /*
             * 第一個(gè)statement參數(shù),其格式為SQL映射文件中namespace.id
             */
            user = (User) session.selectOne("UserMapper.findById", id);
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        } finally {
            session.close();
        }
        
        return user;
    }

}

7、Test01.java

package com.fandou.mybatis.beginning.demo01;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import com.fandou.mybatis.beginning.demo01.dao.UserDao;
import com.fandou.mybatis.beginning.demo01.dao.UserDaoImpl;
import com.fandou.mybatis.beginning.demo01.po.User;

public class Test01 {
    private SqlSessionFactory sqlSessionFactory;
    
    /**
     * 加載MyBatis全局配置,創(chuàng)建sqlSessionFactory
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void testFindById() {
        UserDao userDao = new UserDaoImpl(sqlSessionFactory);
        User user = userDao.findById(1);
        System.out.println("user.id => " + user.getId());
        System.out.println("user.username => " + user.getUsername());
    }
}

至此,所有的代碼編寫完畢,接下來,在mysql數(shù)據(jù)庫中添加以下3條數(shù)據(jù)

id username
1 admin
2 root
3 sqcheng

添加完畢,運(yùn)行Junit測試驗(yàn)證,正常將在控制臺輸入如下信息

user.id => 1
user.username => admin

使用Mapper接口代理

使用Mapper接口代理這種方式開發(fā),需要開發(fā)人員只需要遵守一定的規(guī)范來編寫接口和xml映射文件。接口編寫完,實(shí)現(xiàn)類將在調(diào)用的時(shí)候交由MyBatis框架通過動(dòng)態(tài)代理來生成,開發(fā)人員不需要自行編寫接口的實(shí)現(xiàn)類。

編碼流程

Mapper接口代理的方式編碼流程如下

  • 創(chuàng)建全局配置文件
  • 創(chuàng)建數(shù)據(jù)表POJO對象
  • 創(chuàng)建數(shù)據(jù)表SQL映射文件
  • 創(chuàng)建Mapper接口

實(shí)例代碼

在前面的實(shí)例工程基礎(chǔ)上,新建一個(gè)com.fandou.mybatis.beginning.demo02包,然后再去編寫相關(guān)的代碼,編寫完成后,項(xiàng)目的目錄結(jié)構(gòu)如下


項(xiàng)目工程目錄結(jié)構(gòu)

其中pom.xml、db.properties、User.java和前面的實(shí)例是一樣的,下面不再重復(fù)列出相關(guān)代碼。以下是UserMapper.xml和UserMapper.java以及Test02.java的詳細(xì)代碼
1、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>
<!-- 加載db.properties屬性文件 -->
<properties resource="db.properties"></properties>

<!-- 定義環(huán)境,默認(rèn)使用development -->
  <environments default="development">
  
  <!-- 定義環(huán)境development,配置對應(yīng)的JDBC數(shù)據(jù)庫連接,相關(guān)的連接信息在db.properties屬性文件中定義 -->
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
    
  </environments>
  
  <mappers>
    <mapper resource="com/fandou/mybatis/beginning/demo02/mapper/UserMapper.xml"/>
  </mappers>
</configuration>

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">
<!-- 注意這里的namespace,需要使用UserMapper.java接口類的完整名 -->
<mapper namespace="com.fandou.mybatis.beginning.demo02.mapper.UserMapper">
  <select id="findById" resultType="com.fandou.mybatis.beginning.demo02.po.User">
    select * from user where id = #{id}
  </select>
</mapper>

3、UserMapper.java

package com.fandou.mybatis.beginning.demo02.mapper;

import com.fandou.mybatis.beginning.demo02.po.User;

public interface UserMapper {
    /**
     * 根據(jù)用戶id查詢用戶信息
     * @param id
     * @return
     */
    User findById(int id);
}

4、Test02.java

package com.fandou.mybatis.beginning.demo02;

import java.io.IOException;
import java.io.InputStream;

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 com.fandou.mybatis.beginning.demo02.po.User;
import com.fandou.mybatis.beginning.demo02.mapper.UserMapper;

public class Test02 {
    private SqlSessionFactory sqlSessionFactory;
    
    /**
     * 加載MyBatis全局配置,創(chuàng)建sqlSessionFactory
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void testFindById() {
        /*
         * 調(diào)用UserMapper接口 
         */
        SqlSession session = sqlSessionFactory.openSession();
        UserMapper userMapper = session.getMapper(UserMapper.class);
        User user = userMapper.findById(2);
        
        System.out.println("user.id => " + user.getId());
        System.out.println("user.username => " + user.getUsername());
    }
}

對比代碼,有以下三點(diǎn)發(fā)現(xiàn)
1、UserMapper接口的內(nèi)容和UserDAO接口是一樣的
2、UserMapper.xml中的命名空間namespace變成了全路徑名
3、Test01.java中使用new方式實(shí)例化一個(gè)UserDaoImpl對象,Test02.java則使用MyBatis提供的動(dòng)態(tài)代理方法直接獲取生成的UserMapper接口實(shí)例

Mapper接口代理方式開發(fā)規(guī)范

以下是使用Mapper接口代理方式的一些開發(fā)規(guī)范,必須遵守
1、 Mapper接口的類路徑與Mapper.xml中的namespace保持一致
2、Mapper接口中的方法名和Mapper.xml中每個(gè)statement的id相同
3、Mapper接口方法的入?yún)㈩愋秃蚆apper.xml中每個(gè)sql的parameterType相同
4、Mapper接口方法的返回值類型和Mapper.xml中定義的每個(gè)sql的resultType的類型相同

接下來,在Test02.java上運(yùn)行Junit測試,正常情況下,控制臺將輸出如下結(jié)果

user.id => 2
user.username => root

純注解方式

純注解方式和使用Mapper接口代理的方式不同的地方是不需要寫SQL映射文件,所有的SQL語句直接寫在Mapper接口中。

編碼流程

純注解方式其編碼流程如下

  • 創(chuàng)建全局配置文件
  • 創(chuàng)建數(shù)據(jù)表POJO對象
  • 創(chuàng)建Mapper接口,使用注解并編寫SQL語句

實(shí)例代碼

在前面的實(shí)例工程基礎(chǔ)上,新建一個(gè)com.fandou.mybatis.beginning.demo03包,然后再去編寫相關(guān)的代碼,編寫完成后,項(xiàng)目的目錄結(jié)構(gòu)如下


項(xiàng)目工程目錄結(jié)構(gòu)

其中pom.xml、db.properties、User.java和前面的實(shí)例是一樣的,Test03.java與Test02.java相同,下面不重復(fù)列出。以下是相關(guān)文件的代碼
1、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>
<!-- 加載db.properties屬性文件 -->
<properties resource="db.properties"></properties>

<!-- 定義環(huán)境,默認(rèn)使用development -->
  <environments default="development">
  
  <!-- 定義環(huán)境development,配置對應(yīng)的JDBC數(shù)據(jù)庫連接,相關(guān)的連接信息在db.properties屬性文件中定義 -->
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
    
  </environments>
  
  <mappers>
    <!-- 掃描接口的注解 -->
    <package name="com.fandou.mybatis.beginning.demo03/mapper"/>
  </mappers>
</configuration>

2、UserMapper.java

package com.fandou.mybatis.beginning.demo03.mapper;

import org.apache.ibatis.annotations.Select;

import com.fandou.mybatis.beginning.demo03.po.User;

public interface UserMapper {
    /**
     * 根據(jù)用戶id查詢用戶信息
     * @param id
     * @return
     */
    @Select("select * from user where id = #{id}")
    User findById(int id);
}

接下來,在Test03.java上運(yùn)行Junit測試,假設(shè)查詢的id為3,正常情況下,控制臺將輸出如下結(jié)果

user.id => 3
user.username => sqcheng

注意事項(xiàng)

編寫select語句注意事項(xiàng)

  • 如果parameter為簡單類型
    即基本類型和String類型,#{}中的參數(shù)名稱可以任意
  • 如果parameter普通對象或key-value鍵值對集合類對象
    即POJO類型或Map/Set集合類型,#{}中的參數(shù)名稱必須與POJO的屬性名稱或Map/Set對象中的鍵名一致
  • 如果resultType為POJO類型
    select語句中的列名和POJO對象屬性名必須一致,或額外對屬性和列名進(jìn)行映射綁定

知識拓展

代理模式

代理模式是Java最常用的設(shè)計(jì)模式之一。它將對一個(gè)對象的直接訪問,變?yōu)樵L問這個(gè)對象的代理對象,通過代理對象間接地訪問原本的對象。Java中的代理模式分為動(dòng)態(tài)代理和靜態(tài)代理。靜態(tài)代理是在編碼階段通過編碼實(shí)現(xiàn)的;動(dòng)態(tài)代理則是在運(yùn)行期,動(dòng)態(tài)地為指定的目標(biāo)類生成代理類及其實(shí)例對象。以上實(shí)例中,使用MyBatis的session獲取Mapper接口實(shí)例的方式,使用動(dòng)態(tài)代理模式實(shí)現(xiàn)的。

  • 動(dòng)態(tài)代理
    動(dòng)態(tài)代理其主要原理是利用動(dòng)態(tài)生成與裝載字節(jié)碼的技術(shù),為指定的接口動(dòng)態(tài)創(chuàng)建代理類來實(shí)現(xiàn)。相較于靜態(tài)代理,動(dòng)態(tài)代理更靈活。比較常見的有JDK和CGLIB兩種,下面是兩種方式的對比
對比項(xiàng) JDK動(dòng)態(tài)代理 CGLIB動(dòng)態(tài)代理
代理目標(biāo) 代理有接口的類 通過子類繼承父類方式進(jìn)行代理
消耗時(shí)間
性能
使用場景 每次都需要新建的對象,或代理的類有實(shí)現(xiàn)接口 一次創(chuàng)建可多次使用的對象或代理的類沒有實(shí)現(xiàn)接口
  • 靜態(tài)代理
    靜態(tài)代理要求在開發(fā)階段,為目標(biāo)類編寫對應(yīng)的代理。其優(yōu)點(diǎn)是簡單易行,執(zhí)行效率高;缺點(diǎn)是實(shí)現(xiàn)起來比較死板,工作量大,難適應(yīng)靈活多變的需求。

上一步初識MyBatis

下一步MyBatis全局配置詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容