1. 程式人生 > 實用技巧 >Mybatis入門-02-增刪改查及配置(屬性、別名、對映器)

Mybatis入門-02-增刪改查及配置(屬性、別名、對映器)

一、 前言

一切當以官方文件為基準。

參考視訊狂神說Java-Mybatis

本文之前的操作步驟:Mybatis入門-第一個程式

前置內容:

  • Java
  • maven
  • MySQL
  • JDBC
  • JavaWeb中持久化層的一些知識,如POJO

環境:

  • Java11
  • IDEA 2019.3.3
  • MySQL8
  • mybatis3

路徑:

程式碼

UserMapper:

package com.duzhuan.dao;

import com.duzhuan.pojo.User;

import java.util.List;

/**
 * @Autord: HuangDekai
 * @Date: 2020/9/9 19:42
 * @Version: 1.0
 * @since: jdk11
 */
public interface UserMapper {
    List<User> getUserList();
}

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="com.duzhuan.dao.UserMapper">
    
    <resultMap id="UserMap" type="com.duzhuan.pojo.User">
        <result column="pwd" property="password"/>
    </resultMap>
    
    <select id="getUserList" resultMap="UserMap">
        select * from mybatis.user
    </select>
</mapper>

User:

package com.duzhuan.pojo;

/**
 * @Autord: HuangDekai
 * @Date: 2020/9/9 14:11
 * @Version: 1.0
 * @since: jdk11
 */
public class User {
    private int id;
    private String name;
    private String password;

    public User() {
    }

    public User(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

	/*getter and setter*/
    
    /*toString*/
}

MybatisUtils:

package com.duzhuan.utils;

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.IOException;
import java.io.InputStream;

/**
 * @Autord: HuangDekai
 * @Date: 2020/9/9 21:38
 * @Version: 1.0
 * @since: jdk11
 */
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

二、增刪改查

1.通過id查詢使用者

Usermapper:

package com.duzhuan.dao;

import com.duzhuan.pojo.User;

import java.util.List;

/**
 * @Autord: HuangDekai
 * @Date: 2020/9/9 19:42
 * @Version: 1.0
 * @since: jdk11
 */
public interface UserMapper {
    List<User> getUserList();

    //------------ 新增的語句 --------------------
    User getUserById(int id);
    //------------------------------------------
}

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="com.duzhuan.dao.UserMapper">
    
    <resultMap id="UserMap" type="com.duzhuan.pojo.User">
        <result column="pwd" property="password"/>
    </resultMap>
    
    <select id="getUserList" resultMap="UserMap">
        select * from mybatis.user
    </select>
    
<!--================新增的語句=================-->
    <select id="getUserById" parameterType="int" resultMap="UserMap">
        select * from mybatis.user where id = #{id}
    </select>
<!--=========================================-->
    
</mapper>

paramterType中寫的是getUserById這個方法的引數的資料型別,但是深究下去的話可以知道,在這裡並不區分大小寫,而且涉及到別名,這裡暫時只用知道這裡的int其實對應的是Integer。具體可看Mybatis3-設定-類型別名中的類型別名(typeAliases)。同時,parameterType只能填入一個數據型別,因此,對應的Mapper中的方法顯然只能有一個輸入引數。

#{id}#{}是取引數的一種方式,id即在Mapper中傳入的引數的名字。

Mybatis裡有#{}${}兩種取值方式 ,前者類似於JDBC中的PrepareStatement,而${}則更像是字串拼接,會導致SQL注入。

在UserMapperTest裡新增的測試樣例:

    @Test
    public void getUserByIdTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(1);
        System.out.println(user);

        sqlSession.close();
    }

2.模糊查詢

在UserMapper新增:

List<User> getUserListByName(String name);

在UserMapper.xml的根標籤裡新增:

    <select id="getUserListByName" parameterType="String" resultMap="UserMap">
        select * from mybatis.user where name like concat('%',#{name},'%')
    </select>

concat可以較為方便地實現模糊查詢

測試樣例:

    @Test
    public void getUserListByNameTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserListByName("a");
        for (User user : userList) {
            System.out.println(user);
        }

        sqlSession.close();
    }

結果:

3.增刪改

在Mybatis中,若mybatis-config.xml中配置的transactionManager標籤的type是JDBC,那麼事務自動提交預設是關閉的。

如果要增刪改,就要使用sqlSession.commit()方法提交修改才能持久化。

3.1 增

UserMapper中增加:

int addUser(User user);

insert語句會返回一個int值表示改變的行數,因此該方法設定了返回值資料型別為int。

UserMapper.xml的根標籤裡增加:

    <insert id="addUser" parameterType="com.duzhuan.pojo.User">
        insert into mybatis.user(`id`,`name`,`pwd`) value (#{id},#{name},#{password})
    </insert>

這裡使用的不再是<select>標籤,而是insert。但是id依舊是UserMapper裡對應的方法的的方法名。可以看到,UserMapper中該方法傳入的引數是一個實體類,不是基本型別,我們也沒有對其設定別名,因此parameterType輸入的應該是該實體類的全限定名稱。

仔細觀察可以發現,SQL語句裡用的並非是User.getId,而是直接使用了實體類裡屬性的屬性名。

測試樣例:

    @Test
    public void addUserTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(6, "Gala", "123456");
        int updateLine = mapper.addUser(user);
        if (updateLine>0){
            System.out.println("Add user ------>"+user);
            sqlSession.commit();
        }
        else{
            System.out.println("Failed");
        }
        sqlSession.close();
    }

結果:

3.2 刪

UserMapper中新增方法:

int delUserById(int id);

UserMapper.xml的根標籤裡新增:

    <delete id="delUserById" parameterType="int">
        delete from mybatis.user where id = #{id};
    </delete>

與增加基本一致,只是換成了<delete>標籤。

測試樣例:

    @Test
    public void delUserByIdTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        int id = 6;
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User userById = mapper.getUserById(id);
        int updateLine = mapper.delUserById(id);
        if (updateLine>0){
            System.out.println("Del user -------->"+userById);
            sqlSession.commit();
        }
        else{
            System.out.println("Failed");
        }

        sqlSession.close();
    }

3.3 改

UserMapper中新增方法:

    int updateUser(User user);

UserMapper.xml的根標籤裡新增:

    <update id="updateUser" parameterType="com.duzhuan.pojo.User">
        update mybatis.user set `name` = #{name}, `pwd` = #{password} where `id` = #{id}
    </update>

與增、刪的操作基本一致,只是使用<update>標籤。

測試樣例:

    @Test
    public void updateUserTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(5, "bin", "123456");
        User oldUser = mapper.getUserById(user.getId());

        int updateLine = mapper.updateUser(user);

        if (updateLine > 0){
            System.out.println("Update User from:");
            System.out.println(oldUser);
            System.out.println("to");
            System.out.println(user);
            sqlSession.commit();
        }
        else{
            System.out.println("Failed");
        }
        sqlSession.close();
    }

結果:

三、配置

1.properties

官方文件-XML配置-屬性

這是之前寫的配置檔案(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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="qq123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="com.duzhuan.dao.UserMapper"></mapper>
    </mappers>
</configuration>

property的屬性可以在外部配置,並可以進行動態替換,有利於解耦。

例如將連線資料庫的配置放到外部:

db.properties程式碼:

driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=UTC
username = root
password = qq123456

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>
	<!--=====================add=========================-->
    <properties resource="db.properties"></properties>
	<!--==============================================-->
    
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--================update=================-->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
                 <!--=================================-->
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="com.duzhuan.dao.UserMapper"></mapper>
    </mappers>
</configuration>

部分環境中可能出現xml中有中文註釋不能執行的問題。注意順序,在XML裡標籤前後順序不能改變,即<properties>必須在<environments>前。

由於是Maven專案,因此propertiesresource的值可以直接寫檔名。另外,根據官方文件也可以給出這樣的例子:

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="user"/>
  <property name="password" value="qq123456"/>
</properties>

甚至也可以在 SqlSessionFactoryBuilder.build() 方法中傳入屬性值。

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);

// ... 或者 ...

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);

官方文件給出了優先順序:

如果一個屬性在不只一個地方進行了配置,那麼,MyBatis 將按照下面的順序來載入:

  • 首先讀取在 properties 元素體內指定的屬性。
  • 然後根據 properties 元素中的 resource 屬性讀取類路徑下屬性檔案,或根據 url 屬性指定的路徑讀取屬性檔案,並覆蓋之前讀取過的同名屬性。
  • 最後讀取作為方法引數傳遞的屬性,並覆蓋之前讀取過的同名屬性。

因此,通過方法引數傳遞的屬性具有最高優先順序,resource/url 屬性中指定的配置檔案次之,最低優先順序的則是 properties 元素中指定的屬性。

建議儘量只使用一種方式。

再次執行測試樣例,執行通過就沒問題了。

這裡運行了getUserListTest()獲取結果:

可以正常執行。

2.別名

官方文件-mybatis-配置-類型別名

下面是一些為常見的 Java 型別內建的類型別名。它們都是不區分大小寫的,注意,為了應對原始型別的命名重複,採取了特殊的命名風格。

別名 對映的型別
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator

上面是Mybatis預設有的類型別名。建立自己的類型別名可以使用註解(不利於維護,不推薦),這裡不介紹。下面是使用XML配置類型別名,將com.duzhuan.pojo.User別名設定為User使用:

修改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 resource="db.properties"></properties>
 
    <!--=====================add======================-->
    <typeAliases>
        <typeAlias type="com.duzhuan.pojo.User" alias="User"></typeAlias>
    </typeAliases>
    <!--==============================================-->
    
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="com.duzhuan.dao.UserMapper"></mapper>
    </mappers>
</configuration>

那麼,在這個配置檔案中註冊的Mapper(這裡即com.duzhuan.dao.UserMapper)可以將User作為com.duzhuan.pojo.User使用。

修改UserMapper中帶有com.duzhuan.pojo.User的項為User

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.duzhuan.dao.UserMapper">
    
    <resultMap id="UserMap" type="User">
        <result column="pwd" property="password"/>
    </resultMap>

    <select id="getUserList" resultMap="UserMap">
        select * from mybatis.user
    </select>

    <select id="getUserById" parameterType="int" resultMap="UserMap">
        select * from mybatis.user where id = #{id}
    </select>
    
    <select id="getUserListByName" parameterType="String" resultMap="UserMap">
        select * from mybatis.user where name like concat('%',#{name},'%')
    </select>

    <insert id="addUser" parameterType="User">
        insert into mybatis.user(`id`,`name`,`pwd`) value (#{id},#{name},#{password})
    </insert>

    <delete id="delUserById" parameterType="int">
        delete from mybatis.user where id = #{id};
    </delete>

    <update id="updateUser" parameterType="User">
        update mybatis.user set `name` = #{name}, `pwd` = #{password} where `id` = #{id}
    </update>
</mapper>

這裡再次用getUserListTest去測試:

結果一致。

官方文件中還有使用<package>的,類似於下面:

    <typeAliases>
        <package name="com.duzhuan.pojo"/>
    </typeAliases>

這樣就能直接把包內的所有類的類名作為別名。但是這樣的話別名就只能是類名,而<typeAliase>可以用alias屬性命名別的名字。

3.對映器

mybatis官方文件-設定-對映器

對映器,即mappers。

我們在上面將UserMapper繫結的操作使用的是使用對映器介面實現類的完全限定名:

    <mappers>
        <mapper class="com.duzhuan.dao.UserMapper"></mapper>
    </mappers>

這種方式要求:

  • Mapper與其對應的Mapper.xml同名
  • Mapper於其對應的Mapper.xml在同一目錄

其餘方法觀看官方文件即可,對於下面這種方式不推薦使用:

<!-- 使用完全限定資源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>