1. 程式人生 > >《SpringBoot從入門到放棄》之第(八)篇——SpringBoot整合Mybatis(大型專案開發技術首選)

《SpringBoot從入門到放棄》之第(八)篇——SpringBoot整合Mybatis(大型專案開發技術首選)

一千個讀者有一千個哈姆雷特。

你們的專案中,傾向於把資料庫的語句寫在Java類裡,還是使用Mybatis框架呢?

相對來說,做一些複雜的大專案,用第三方開源的Mybatis會比較好。把資料庫操作語句抽取出來,寫在xml檔案,方便管理。

個人比較傾向於使用Mybatis,還有Mybatis的逆向工程,聽說很好使,但本人還沒用過,後續會加上部落格,敬請期待吧!

專案結構,標註的是新增的檔案:

本篇部落格接著上一篇,在 pom.xml 裡新增 Mybatis 的jar依賴:

		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.1</version>
		</dependency>

在 resources 資料夾下建立 mybatis-config.xml 配置檔案,與application.properties同一級:

<?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>

    <!-- 全域性配置引數 -->
    <settings>
        <!-- 使全域性的對映器啟用或禁用快取。 -->
        <setting name="cacheEnabled" value="true"/>
        <!-- debug 模式列印 sql 語句 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

</configuration>

介面 UserDao,注意需要新增 @Mapper 註解,否則無法呼叫Mybatis框架:

或者在啟動的類加上:@MapperScan("com.test.dao") 註解,掃描的是Dao層的包。這樣就不需要在每個 Dao 類里加入註解@Mapper 了。

package com.test.dao;

import com.test.entity.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface UserDao {

    /**
     * 新增使用者
     * @param user
     * @return
     */
    Integer addUserMybatis(User user);

    /**
     * 根據id刪除使用者
     * @param id
     * @return
     */
    Integer deleteUserMybatis(Integer id);

    /**
     * 更新使用者資訊
     * @param user
     * @return
     */
    Integer updateUserMybatis(User user);

    /**
     * 查詢所有使用者資訊
     * @return
     */
    List<User> getUserMybatis();
}

業務層,UserServiceMybatis(為了和之前的UserService做區分):

package com.test.service;

import com.test.dao.UserDao;
import com.test.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
public class UserServiceMybatis {

    @Autowired
    private UserDao userDao;

    /**
     * 新增使用者
     * @param user
     * @return
     */
    @Transactional(readOnly = false)
    public Integer addUserMybatis(User user){
        return userDao.addUserMybatis(user);
    }

    /**
     * 根據id刪除使用者
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    public Integer deleteUserMybatis(Integer id){
        return userDao.deleteUserMybatis(id);
    }

    /**
     * 更新使用者資訊
     * @param user
     * @return
     */
    @Transactional(readOnly = false)
    public Integer updateUserMybatis(User user){
        return userDao.updateUserMybatis(user);
    }

    /**
     * 查詢所有使用者資訊
     * @return
     */
    @Transactional(readOnly = true)
    public List<User> getUserMybatis(){
        return userDao.getUserMybatis();
    }

}

說明:可以看到我使用了事務註解 @Transactional(readOnly = true),@Transactional(readOnly = false),在一些增、刪、改、呼叫儲存過程的方法中,需要把 readOnly 設定為 false,預設的是false,可以不新增。以後的開發中,在一些關鍵的查詢操作,可以指定 readOnly 屬性。

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.test.dao.UserDao">

    <!-- 資料庫欄位與實體類欄位的對映,column是資料庫的列名,property是實體類的屬性名 -->
    <resultMap id="UserBaseResultMap" type="com.test.entity.User">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="signature" jdbcType="VARCHAR" property="signature"/>
    </resultMap>

    <!-- 新增使用者,id就是方法名 -->
    <insert id="addUserMybatis">
        insert into t_user (name,signature) values (#{name},#{signature})
    </insert>

    <!-- 刪除使用者,id就是方法名,parameterType可以寫,也可以不寫。 -->
    <delete id="deleteUserMybatis" parameterType="java.lang.Integer">
        delete from t_user where id = #{id,jdbcType=INTEGER}
    </delete>

    <!-- 修改使用者 -->
    <update id="updateUserMybatis">
        update t_user set name = #{name},signature =#{signature} where id = #{id}
    </update>

    <!-- 查詢所有使用者,將結果對映到 UserBaseResultMap 對應的屬性中,如果有多個結果集,會返回多個實體類 -->
    <select id="getUserMybatis" resultMap="UserBaseResultMap">
        select * from t_user
    </select>

</mapper>

需要注意的是:①mapper namespace="com.test.dao.UserDao"

②諸如 select、insert、update的id,對應的是Dao層的方法名。配置檔案的 id 是不允許重複的,意思就是說,在 Dao 層裡,不允許方法過載

想學習更多關於Mybatis的知識,可以去Mybatis中文官網學習。

MybatisController,注意,在類的簽名裡使用了 @RestController 的註解,預設的返回 Json 格式資料。

package com.test.web;

import com.test.entity.User;
import com.test.service.UserServiceMybatis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class MybatisController {

    @Autowired
    private UserServiceMybatis userServiceMybatis;

    /**
     * 新增使用者
     * @param name
     * @param signature
     * @return
     */
    @RequestMapping(value = "/addUserMybatis")
    public Map<String,Integer> addUserMybatis(@RequestParam String name, @RequestParam String signature){
        User u=new User();
        u.setName(name);
        u.setSignature(signature);
        Integer count = userServiceMybatis.addUserMybatis(u);
        Map<String, Integer> map = new HashMap<>();
        map.put("count", count);
        return map;
    }

    /**
     * 根據id刪除使用者資訊
     * @param id
     * @return
     */
    @RequestMapping(value = "/deleteUserMybatis")
    public Map<String,Integer> deleteUserMybatis(@RequestParam Integer id){
        Integer count = userServiceMybatis.deleteUserMybatis(id);
        Map<String, Integer> map = new HashMap<>();
        map.put("count", count);
        return map;
    }

    /**
     * 更新使用者資訊
     * @param id
     * @param name
     * @param signature
     * @return
     */
    @RequestMapping(value = "/updateUserMybatis")
    public Map<String,Integer> updateUserMybatis(@RequestParam Integer id,@RequestParam String name, @RequestParam String signature){
        User u=new User();
        u.setId(id);
        u.setName(name);
        u.setSignature(signature);
        Integer count = userServiceMybatis.updateUserMybatis(u);
        Map<String, Integer> map = new HashMap<>();
        map.put("count", count);
        return map;
    }

    /**
     * 查詢所有使用者資訊
     * @return
     */
    @RequestMapping(value = "/getUserMybatis")
    public List<User> getUserMybatis(){
        List<User> list = userServiceMybatis.getUserMybatis();
        return list;
    }

}

最關鍵的,application.properties 配置:

# 服務埠
server.port=9090

# 資料庫連線配置
spring.datasource.url=jdbc:mysql://localhost:3306/mytest
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

# Mybatis配置
# Mybatis掃描的mapper檔案
mybatis.mapperLocations=classpath:mappings/**/*.xml
# 掃描哪個包下的域物件
mybatis.typeAliasesPackage=com.test.entity
# Mybatis配置檔案
mybatis.configLocation=classpath:mybatis-config.xml
# mybatis.typeAliasesSuperType 掃描包以下面的這個類作為父類的域物件

如果遇到下面類似的問題,就是因為 Mybatis 的配置沒有完善

O的K,萬事俱備只欠東風,用吊炸天的 postman 測試一下:

①測試新增使用者,很OK:

去到編輯器的控制檯檢視列印的資料庫語句:

Registering transaction synchronization for SqlSession [[email protected]]
JDBC Connection [[email protected] wrapping [email protected]] will be managed by Spring
==>  Preparing: insert into t_user (name,signature) values (?,?) 
==> Parameters: 小米(String), 為發燒而生(String)
<==    Updates: 1

②查詢所有使用者:

③修改使用者:

④刪除使用者:http://localhost:9090/deleteUserMybatis?id=2

完美整合Mybatis!

說明:其實也可以直接從 Controller 層呼叫 Dao 層,而不需要 Service 層,也是可以實現邏輯。加多一層 Service 能更好的增加許可權控制、事務管理或者其它功能。