天天看點

Springboot 整合tk-mybatis , 媽媽,我再也不想敲CRUD的代碼了!

前言

碼農這一生,做的最多的四件事,不是吃喝玩樂,而是  增加(Create)、檢索(Retrieve)、更新(Update)和删除(Delete)  。

淚目。

為何我要寫這篇文章,是有感而發,請看圖:

Springboot 整合tk-mybatis , 媽媽,我再也不想敲CRUD的代碼了!

哈哈,雖然看着圖一樂,但是大部分碼農的工作生活确實作狀如此。

也許會有人說了,其實很多crud的代碼也隻是複制粘貼而已,稍微改改就好。

這确實沒錯,但是人天性嗜懶,日複一日,不免對複制粘貼也産生了些許倦意。

那麼為了我們每天都能元氣滿滿,我們盡可能減少大部分我們‘重複’ 的代碼。 

 曾寫過一篇 Springboot 整合Mybatis 使用Mybatis-plus 靈活開發 ,也是可以省掉非常多的crud代碼

那麼今天,我需要介紹給大家的是 TK-Mybatis。

正文

慣例,今天的實戰執行個體目錄結構:

Springboot 整合tk-mybatis , 媽媽,我再也不想敲CRUD的代碼了!

目前不管是mybatis-plus ,還是tk-mybatis。 幫我們省掉的代碼,其實都是對于單表操作而言。

(是以一些複雜的sql語句,我們還是可以自己額外編寫,是以額外編寫的,我們如往常一樣寫在mapper.xml裡面即可)

也就是說,對于單獨一個表的crud操作,一些正常的crud相關代碼,都是可以幫我們省掉的,我們不用再寫了,包括不僅限于:

1.查詢該表所有資料
2.根據條件該表查詢該表所有資料
3.根據主鍵該表查詢該表單個資料
4.根據條件查詢該表單個資料
5.檢測資料是否存在
6.統計該表資料條數
7.根據主鍵删除資料
8.根據條件删除資料
9.根據主鍵修改資料
10.根據條件修改資料
11.新增資料
12.分頁查詢
13.當然還有挺多,不一一列舉了      

建立一個springboot項目,在pom.xml裡導入用到的依賴:

<!--jdbc驅動-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--mybatis操作資料庫有關-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--連接配接mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--使用阿裡巴巴的druid資料源,有利于監控sql的執行情況-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--通用mapper-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>

        <!--添加lombok支援,可以省掉寫get和set方法-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
            <optional>true</optional>
        </dependency>
        <!--使用fastjson來操作json資料-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.58</version>
        </dependency>
        <!--spring boot web方面的支援-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>      

資料庫表,簡單一張表:

Springboot 整合tk-mybatis , 媽媽,我再也不想敲CRUD的代碼了!

對于的User.java實體類:

import lombok.Data;
import javax.persistence.*;

/**
 * @Author : JCccc
 * @CreateTime : 2020/8/13
 * @Description :
 **/
@Data
@Table(name="user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY,generator = "JDBC")
    private Integer id;
    @Column(name = "name")
    private String name;
    @Column(name = "age")
    private Integer age;
}      

然後是UserMapper.java(注意看細節,繼承了Mapper<User> ,隻要繼承了這個Mapper,那麼文章前頭提到的那些代碼和sql,我們都不用再去寫了,我們隻需要寫一些多表的,業務複雜的需要額外擴充的就行。:

import tk.mybatis.mapper.common.Mapper;
import java.util.List;
import java.util.Map;

/**
 * @Author : JCccc
 * @CreateTime : 2020/8/13
 * @Description :
 **/
public interface UserMapper extends Mapper<User> {
    
    //額外擴充的方法,如一些複雜的查詢語句等
    List<Map> getMyCustom(int age);
}      

細心的人發現了,我們這次的mapper上面沒有寫@Mapper。

是的,我們現在進行一個關鍵的操作,在啟動類上,使用tk-mybatis的掃描mapper注解:

Springboot 整合tk-mybatis , 媽媽,我再也不想敲CRUD的代碼了!

pojo和mapper 兩層已經完畢了,那麼對接持久層需要做的我們已經完畢了。

service層,我們在這層為了方面項目的擴充,後期能省掉更多的接口複寫代碼(是不是很多人很煩service層裡面的代碼跟mapper層對于一些普通的crud操作,基本代碼沒什麼差別),

我們需要做一個base層,也就是後續其他業務的表擴充,都同一繼承和實作base層即可。

BaseService.java :

import org.apache.ibatis.session.RowBounds;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;

/**
 * @Author : JCccc
 * @CreateTime : 2020/8/13
 * @Description :
 **/
public interface BaseService<T> extends Mapper<T> {
    @Override
    int deleteByPrimaryKey(Object o);

    @Override
    int delete(T o);

    @Override
    int insert(T o);

    @Override
    int insertSelective(T o);

    @Override
    List<T> selectAll();

    @Override
    T selectByPrimaryKey(Object o);

    @Override
    public int selectCount(T o);

    @Override
    public List<T> select(T o);

    @Override
    public T selectOne(T o);

    @Override
    public int updateByPrimaryKey(T o);

    @Override
    public int updateByPrimaryKeySelective(T o);

    @Override
    public int deleteByExample(Object o);

    @Override
    public List<T> selectByExample(Object o);

    @Override
    public int selectCountByExample(Object o);

    @Override
    public T selectOneByExample(Object o);

    @Override
    public int updateByExample(T o, Object o2);

    @Override
    public int updateByExampleSelective(T o, Object o2);

    @Override
    public List<T> selectByExampleAndRowBounds(Object o, RowBounds rowBounds);

    @Override
    public List<T> selectByRowBounds(T o, RowBounds rowBounds);
}      

BaseServiceImpl.java:

import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;

/**
 * @Author : JCccc
 * @CreateTime : 2020/8/13
 * @Description :
 **/
public abstract class BaseServiceImpl<T> implements BaseService<T> {

    @Autowired
    private Mapper<T> mapper;


    @Override
    public int deleteByPrimaryKey(Object o) {
        return mapper.deleteByPrimaryKey(o);
    }

    @Override
    public int delete(T t) {
        return mapper.delete(t);
    }

    @Override
    public int insert(T t) {
        return mapper.insert(t);
    }

    @Override
    public int insertSelective(T t) {
        return mapper.insertSelective(t);
    }

    @Override
    public List<T> selectAll() {
        return mapper.selectAll();
    }

    @Override
    public int selectCount(T t) {
        return mapper.selectCount(t);
    }

    @Override
    public List<T> select(T t) {
        return mapper.select(t);
    }

    @Override
    public T selectOne(T t) {
        return mapper.selectOne(t);
    }

    @Override
    public int updateByPrimaryKey(T t) {
        return mapper.updateByPrimaryKey(t);
    }

    @Override
    public int updateByPrimaryKeySelective(T t) {
        return mapper.updateByPrimaryKeySelective(t);
    }

    @Override
    public int deleteByExample(Object t) {
        return mapper.deleteByExample(t);
    }

    @Override
    public List<T> selectByExample(Object t) {
        return mapper.selectByExample(t);
    }

    @Override
    public int selectCountByExample(Object t) {
        return mapper.selectCountByExample(t);
    }

    @Override
    public T selectOneByExample(Object o) {
        return mapper.selectOneByExample(o);
    }

    @Override
    public int updateByExample(T t, Object o) {
        return mapper.updateByExample(t, o);
    }

    @Override
    public int updateByExampleSelective(T t, Object o) {
        return mapper.updateByExampleSelective(t, o);
    }

    @Override
    public List<T> selectByExampleAndRowBounds(Object o, RowBounds rowBounds) {
        return mapper.selectByExampleAndRowBounds(o, rowBounds);
    }

    @Override
    public List<T> selectByRowBounds(T t, RowBounds rowBounds) {
        return mapper.selectByRowBounds(t, rowBounds);
    }

    @Override
    public boolean existsWithPrimaryKey(Object o) {
        return mapper.existsWithPrimaryKey(o);
    }

    @Override
    public T selectByPrimaryKey(Object o) {
        return mapper.selectByPrimaryKey(o);
    }
}      

ok,業務層的base層已經完成,回歸業務,

UserService.java:

import com.jc.tkmybatis.base.BaseService;
import com.jc.tkmybatis.pojo.User;
import java.util.List;
import java.util.Map;

/**
 * @Author : JCccc
 * @CreateTime : 2020/8/13
 * @Description :
 **/
public interface UserService extends BaseService<User> {


    //僅僅需要編寫額外擴充的業務方法
    List<Map>  getMyCustom(int age);
    
}      

UserServiceImpl.java:

import com.jc.tkmybatis.base.BaseServiceImpl;
import com.jc.tkmybatis.mapper.UserMapper;
import com.jc.tkmybatis.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;

/**
 * @Author : JCccc
 * @CreateTime : 2020/8/13
 * @Description :
 **/
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements UserService {

    //UserMapper需要繼承tk-myabtis的Mapper,這樣才能順利使用到tk-mybatis幫我們寫好的N多mapper層方法和sql語句
    @Autowired
     UserMapper userMapper;


    //僅僅需要編寫額外擴充的業務方法
    @Override
    public List<Map> getMyCustom(int age) {
        return userMapper.getMyCustom(age);
    }

}      

到這裡,我們其實整合tk-mybatis已經完畢了!(後面有controller層來示範怎麼使用)

因為我們為了確定可以額外擴充,我們還是建了mapper.xml的,是以我們在yml加上對于的mapper.xml檔案掃描配置:

mybatis:
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml      

對于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.jc.tkmybatis.mapper.UserMapper">
    
    <select id="getMyCustom" resultType="java.util.HashMap">
      SELECT *
      FROM  user
      WHERE age>=#{age}
    </select>
    
</mapper>      

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>

    <settings>
        <setting name="useGeneratedKeys" value="true"/>
        <setting name="useColumnLabel" value="true"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>      

controller層,我們寫一些curd的接口來進行使用測試:

UserController.java 

PS: 我們在controller層注入 UserService後,我們就可以使用tk-mybatis幫我們實作的那一堆方法了。

Springboot 整合tk-mybatis , 媽媽,我再也不想敲CRUD的代碼了!
import com.jc.tkmybatis.pojo.User;
import com.jc.tkmybatis.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;

/**
 * @Author : JCccc
 * @CreateTime : 2020/8/13
 * @Description :
 **/
@RestController
public class UserController {

    @Autowired
    UserService userService;

    /**
     * 新增
     * @return
     */
    @PostMapping("addOne")
    public int addOne() {
        User user=new User();
        user.setName("jc");
        user.setAge(10);
        return userService.insert(user);
    }

    /**
     * 擷取所有 分頁
     * @return
     */
    @GetMapping("getAllByPage")
    public List<User> getAllByPage() {
        RowBounds rowBounds=new RowBounds(0,3);
        return userService.selectByRowBounds(new User(),rowBounds);
    }

    /**
     * 擷取某個
     * @return
     */
    @GetMapping("getOne")
    public User getOne() {
        User user=new User();
        user.setId(1);
        return userService.selectOne(user);
    }

    /**
     * 擷取所有
     * @return
     */
    @GetMapping("getAll")
    public List<User> getAll() {

        return userService.selectAll();
    }

    /**
     * 修改
     * @return
     */
    @GetMapping("updateOne")
    public int updateOne() {
        User user=new User();
        user.setId(1);
        user.setName("TG");
        return userService.updateByPrimaryKeySelective(user);
    }


    /**
     * 額外擴充的
     * @return
     */
    @GetMapping("getMyCustom")
    public List<Map> getMyCustom() {
        return userService.getMyCustom(1);
    }

}      

接口的測試,大家自行使用postman或者api post等測試就ok,我就不一一列舉了。

ps: 上面代碼裡面的分頁查詢,是用到了tk-mybatis裡的方法 selectByRowBounds 。 

習慣用pagehelper的依然可以使用,添加分頁插件依賴:

<dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>      

使用示例:

/**
     * 擷取所有 分頁 PageHelper
     * @return
     */
    @GetMapping("getAllByPage")
    public PageInfo getAll() {
        PageHelper.startPage(1, 2);
        PageInfo pageInfo = new PageInfo(userService.selectAll());
        return pageInfo;
    }      

到此,大家應該是學會整合使用了,我建議,我們不僅要求自己處于單純的使用,稍微深入一點點了解也是需要的(這樣說不定突然感興趣了,自己就去深挖了)。

抛磚引玉

為什麼能省掉這麼多代碼?  

說白了,就是tk-mybatis幫我們寫了呗。

我們知道mapper是對接持久層的,那麼我們看看我們mapper做了什麼?  沒錯,就是繼承了tk-mybatis的Mapper<T>:

Springboot 整合tk-mybatis , 媽媽,我再也不想敲CRUD的代碼了!

看到這個代碼,如果你用過JPA,那麼你會非常熟悉這些(沒接觸過JPA的可以看我這篇,你就知道為啥我會這

那麼我們需要的就是了解這些Mapper裡面有哪些方法,例如

BaseMapper<T> :

/**
   * 儲存一個實體,null屬性也會儲存
   * 
   * @param record
   * @return
   */
  int insert(T record);
 
  /**
   * 儲存一個實體,null屬性不會儲存
   * 
   * @param record
   * @return
   */
  int insertSelective(T record);
 
  /**
   * 根據實體屬性作為條件進行删除,查詢條件使用等号
   */
  int delete(T record);
 
  /**
   * 根據主鍵更新屬性不為null的值
   */
  int updateByPrimaryKeySelective(T record);
 
  /**
   * 根據實體中的屬性值進行查詢,查詢條件使用等号
   */
  List<T> select(T record);
 
  /**
   * 查詢全部結果,select(null)方法能達到同樣的效果
   */
  List<T> selectAll();
 
  /**
   * 根據實體中的屬性進行查詢,隻能有一個傳回值,有多個結果是抛出異常,查詢條件使用等号
   */
  T selectOne(T record);
 
  /**
   * 根據實體中的屬性查詢總數,查詢條件使用等号
   */
  int selectCount(T record);      

ExampleMapper ,RowBoundsMapper 這些也是需要了解的(小聲說下,認真操作的在文章前面有些方法用到了RowBounds,其實是用來分頁的~ )。

這篇文章算是一個tk-mybatis的整合引玉篇吧,把BaseService裡面的方法都使用調試下,那麼使用層面應該沒有問題了。