Spring Boot Mybatis 使用教程


Mybatis 在當下互聯網開發環境,十分重要。本章主要講述 Mybatis 如何使用。

從本系列開始,都需要用到 mysql 數據庫 和其他一些參考的數據庫。請准備相關環節。本章需要以下環境支撐:

  • mysql 5.6+
  • jdk1.8+
  • spring boot 2.1.6
  • idea 2018.1

本項目源碼下載

1 准備數據庫

數據庫教程系列都是使用相同的數據,如在 Spring Boot JDBC 使用教程使用的一樣

字段 類型 主鍵 說明
id int 自動編號
user_name varchar(100) 用戶名
password varchar(255) 密碼
last_login_time date 最近登錄時間
sex tinyint 性別 0男 1女 2其他

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `last_login_time` datetime DEFAULT NULL,
  `sex` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=armscii8;

-- ----------------------------
-- Records of t_user
-- ----------------------------
BEGIN;
INSERT INTO `t_user` VALUES (1, 'json', '123', '2019-07-27 16:01:21', 1);
INSERT INTO `t_user` VALUES (2, 'jack jo', '123', '2019-07-24 16:01:37', 1);
INSERT INTO `t_user` VALUES (3, 'manistal', '123', '2019-07-24 16:01:37', 1);
INSERT INTO `t_user` VALUES (4, 'landengdeng', '123', '2019-07-24 16:01:37', 1);
INSERT INTO `t_user` VALUES (5, 'max', '123', '2019-07-24 16:01:37', 1);
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

2 新建 Spring Boot 工程項目

  1. File > New > Project,如下圖選擇 Spring Initializr 然后點擊 【Next】下一步
  2. 填寫 GroupId(包名)、Artifact(項目名) 即可。點擊 下一步
    groupId=com.fishpro
    artifactId=mybatis
  3. 選擇依賴 Spring Web Starter 前面打鈎,勾選SQL選項的 mybatis , mysql。
  4. 項目名設置為 spring-boot-study-mybatis.

3 依賴引入 Pom.xml 配置

在新建工程的時候,如果選擇 Mybatis 依賴,則不需要單獨配置,以下是本項目的全部依賴。

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3 Mybatis 的工程配置 application.yml

無論是 jdbc 還是 mybatis 都需要對 數據源進行配置,而且配置項是一樣的。除了數據源基礎的配置,我們還需要配置 mybatis 的映射文件 *.xml 的路徑,mybatis 的獨立 config.xml 文件路徑等。

  • mapper-locations 配置實體與數據庫表的映射文件xml位置,我們配置為 /src/main/resource/mybatis/**maper.xml
  • map-underscore-to-camel-case 開啟mybatis的駝峰命名轉換
  • type-aliases-package 指定 實體 domain 的類,這是 com.fishpro 下所有以 domain 結尾的實體類。
server:
  port: 8086
mybatis:
  configuration:
    map-underscore-to-camel-case: true
  mapper-locations: mybatis/**/*Mapper.xml
  type-aliases-package: com.fishpro.**.domain

針對 mybatis 的配置,我們也可以把所有 mybatis 配置配置到單獨的 config 文件中。

5 編寫示例代碼

這里我們首次使用到 三層結構來演示本項目,即 controller-service-dao-mapper-mybatis

mybatis三層結構示例

本示例包括新增的頁面

  1. src/main/java/com/fishpro/mybatis/controller/UserController.java 控制層 rest api
  2. src/main/java/com/fishpro/mybatis/domain/UserDO.java 實體對象
  3. src/main/java/com/fishpro/mybatis/dao/UserDao.java Dao數據庫訪問層
  4. src/main/java/com/fishpro/mybatis/service/UserService.java 服務層包括了接口+接口實現
  5. src/main/java/com/fishpro/mybatis/service/impl/UserServiceImpl.java 服務層包括了接口+接口實現
  6. src/main/resources/mybatis/UserMapper.xml 映射 xml 文件

5.1 映射文件 UserMapper.xml

UserMapper.xml 是一個以 mybatis 語法來編寫的 xml 映射文件。

+ mapper 節點是根節點 具有屬性 namespace 表示 mapper 對應的 java 的 Dao 接口類
  |--select 查詢節點
    |--where
    |--choose
        |--when
        |--otherwise
  |--insert 插入節點
  |--update 更新節點
  |--delete 刪除節點

詳細的代碼如下

<?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.fishpro.mybatis.dao.UserDao">
    <select id="get" resultType="com.fishpro.mybatis.domain.UserDO">
		select `id`,`user_name`,`password`,`last_login_time`,`sex` from t_user where id = #{value}
	</select>
    <select id="list" resultType="com.fishpro.mybatis.domain.UserDO">
        select `id`,`user_name`,`password`,`last_login_time`,`sex` from t_user
        <where>
            <if test="id != null   and id != '-1' " > and id = #{id} </if>
            <if test="userName != null  and userName != '' " > and user_name = #{userName} </if>
            <if test="password != null  and password != '' " > and password = #{password} </if>
            <if test="lastLoginTime != null  and lastLoginTime != '' " > and last_login_time = #{lastLoginTime} </if>
            <if test="sex != null   and sex != '-1' " > and sex = #{sex} </if>
        </where>
        <choose>
            <when test="sort != null and sort.trim() != ''">
                order by ${sort} ${order}
            </when>
            <otherwise>
                order by id desc
            </otherwise>
        </choose>
        <if test="offset != null and limit != null">
            limit #{offset}, #{limit}
        </if>
    </select>
    <select id="count" resultType="int">
        select count(*) from t_user
        <where>
            <if test="id != null   and id != '-1'  " > and id = #{id} </if>
            <if test="userName != null  and userName != ''  " > and user_name = #{userName} </if>
            <if test="password != null  and password != ''  " > and password = #{password} </if>
            <if test="lastLoginTime != null  and lastLoginTime != ''  " > and last_login_time = #{lastLoginTime} </if>
            <if test="sex != null   and sex != '-1'  " > and sex = #{sex} </if>
        </where>
    </select>
    <insert id="save" parameterType="com.fishpro.mybatis.domain.UserDO" useGeneratedKeys="true" keyProperty="id">
		insert into t_user
		(
			`user_name`,
			`password`,
			`last_login_time`,
			`sex`
		)
		values
		(
			#{userName},
			#{password},
			#{lastLoginTime},
			#{sex}
		)
	</insert>
    <update id="update" parameterType="com.fishpro.mybatis.domain.UserDO">
        update t_user
        <set>
            <if test="userName != null">`user_name` = #{userName}, </if>
            <if test="password != null">`password` = #{password}, </if>
            <if test="lastLoginTime != null">`last_login_time` = #{lastLoginTime}, </if>
            <if test="sex != null">`sex` = #{sex}</if>
        </set>
        where id = #{id}
    </update>
    <delete id="remove">
		delete from t_user where id = #{value}
	</delete>

    <delete id="batchRemove">
        delete from t_user where id in
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>
</mapper>

5.2 實體對象 UserDO

與數據庫表對應的(可自定義)對象實體類


public class UserDO {
    private Integer id;
    private String userName;
    private String password;
    private Integer sex;
    private Date lastLoginTime;

    public Integer getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getSex() {
        return sex;
    }

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

    public Date getLastLoginTime() {
        return lastLoginTime;
    }

    public void setLastLoginTime(Date lastLoginTime) {
        this.lastLoginTime = lastLoginTime;
    }
}

5.3 數據庫訪問層 UserDao

Dao 是一個接口層,接口方法對應 mybatis/**Mapper.xml 中 Mapper 節點下的 id 值。例如上面的 <select id="get" resultType="com.fishpro.mybatis.domain.UserDO"> 那么對應的接口方法 UserDO get(Integer id)

Dao 必須使用 @Mappger注解,才能實現從Dao到Mapper.xml的映射


/**
 * 數據庫訪問層 用戶Dao t_user
 * @author fishpro
 */
@Mapper
public interface UserDao {
    /**
     * 對應節點 select id="get" resultType="com.fishpro.mybatis.domain.UserDO"
     * */
    UserDO get(Integer id);
    /**
     * 對應節點 select id="list" resultType="com.fishpro.mybatis.domain.UserDO"
     * */
    List<UserDO> list(Map<String, Object> map);
    /**
     * 對應節點 select id="count" resultType="int"
     * */
    int count(Map<String, Object> map);
    /**
     * 對應節點 insert id="save" parameterType="com.fishpro.mybatis.domain.UserDO" useGeneratedKeys="true" keyProperty="id"
     * */
    int save(UserDO user);
    /**
     * 對應節點 update id="update" parameterType="com.fishpro.mybatis.domain.UserDO"
     * */
    int update(UserDO user);
    /**
     * 對應節點 delete id="remove"
     * */
    int remove(Integer id);
    /**
     * 對應節點 delete id="batchRemove"
     * */
    int batchRemove(Integer[] ids);
}

5.4 服務類 UseService

注意 UserServiceImpl 一定要使用 @Service 注解,才能實現 UserService類自動注入功能
在本示例中只是簡單的增刪改查功能
UserService 接口類

public interface UserService {

    UserDO get(Integer id);

    List<UserDO> list(Map<String, Object> map);

    int count(Map<String, Object> map);

    int save(UserDO user);

    int update(UserDO user);

    int remove(Integer id);

    int batchRemove(Integer[] ids);
}

UserServiceImpl 實現類


@Service
public class UserServiceImpl implements UserService {
	@Autowired
	private UserDao userDao;
	
	@Override
	public UserDO get(Integer id){
		return userDao.get(id);
	}
	
	@Override
	public List<UserDO> list(Map<String, Object> map){
		return userDao.list(map);
	}
	
	@Override
	public int count(Map<String, Object> map){
		return userDao.count(map);
	}
	
	@Override
	public int save(UserDO user){
		return userDao.save(user);
	}
	
	@Override
	public int update(UserDO user){
		return userDao.update(user);
	}
	
	@Override
	public int remove(Integer id){
		return userDao.remove(id);
	}
	
	@Override
	public int batchRemove(Integer[] ids){
		return userDao.batchRemove(ids);
	}
	
}

5.5 控制層實現 Rest Api 增刪改查接口 UserController

本示例代碼使用標准的 Restful 風格編寫 具體代碼如下:


/**
 * RESTful API + Mybatis 風格示例 對資源 user 進行操作
 * 本示例沒有使用數據庫,也沒有使用 service 類來輔助完成,所有操作在本類中完成
 * 請注意幾天
 *    1.RESTful 風格使用 HttpStatus 狀態返回 GET PUT PATCH DELETE 通常返回 201 Create ,DELETE 還有時候返回 204 No Content
 *    2.使用 RESTful 一定是要求具有冪等性,GET PUT PATCH DELETE 本身具有冪等性,但 POST 不具備,無論規則如何定義冪等性,需要根據業務來設計冪等性
 *    3.RESTful 不是神丹妙葯,實際應根據實際情況來設計接口
 * */
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 測試用 參數為 name
     * */
    @RequestMapping("/hello")
    public String hello(String name){
        return "Hello "+name;
    }

    /**
     * SELECT 查詢操作,返回一個JSON數組
     * 具有冪等性
     * */
    @GetMapping("/users")
    @ResponseStatus(HttpStatus.OK)
    public Object getUsers(){

        return userService.list(new HashMap<>());
    }

    /**
     * SELECT 查詢操作,返回一個新建的JSON對象
     * 具有冪等性
     * */
    @GetMapping("/users/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Object getUser(@PathVariable("id") String id){

        if(null==id){
            return  null;
        }
        return userService.get(Integer.valueOf(id));
    }

    /**
     * 新增一個用戶對象
     * 非冪等
     * 返回 201 HttpStatus.CREATED 對創建新資源的 POST 操作進行響應。應該帶着指向新資源地址的 Location 頭
     * */
    @PostMapping("/users")
    @ResponseStatus(HttpStatus.CREATED)
    public Object addUser(@RequestBody UserDO user){
        if(user.getId()==0){
            return null;
        }
        userService.save(user);
        return user;
    }

    /**
     * 編輯一個用戶對象
     * 冪等性
     * */
    @PutMapping("/users/{id}")
    @ResponseStatus(HttpStatus.CREATED)
    public Object editUser(@PathVariable("id") String id, @RequestBody UserDO user){

        userService.update(user);
        return user;
    }

    /**
     * 刪除一個用戶對象
     * 冪等性
     * 返回 HttpStatus.NO_CONTENT 表示無返回內容
     * */
    @DeleteMapping("/users/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable("id") String id){
        userService.remove(Integer.valueOf(id));
    }
}

6 運行示例

右鍵 MybatisApplication > Run MybatisApplication 在瀏覽器輸入 http://localhost:8086/api/user/users

使用 PostMan 測試工具可測試 GET\POST\PUT\DELETE 動作的 Restful api

mybatis 查詢所有用戶

7 問題思考

  1. 如何自動生成代碼
  2. 如何動態配置數據源
  3. 如何分表分庫
  4. xml的詳細語法由哪些坑
  5. xml 好還是 注解好
  6. 如何解決事物處理
  7. 擴庫事物如何處理

下一章節我們演示下使用 注解來實現

本項目源碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM