mybatis 想要支持 data-jpa 的功能? 只需一個依賴就夠了!!!

mybatis 怎麼才能支持 data-jpa?

前言

spring-data-jpa 的只寫接口便可以 CRUD 的能力真的是好爽,然而 mybatis 寫 sql 的靈活又讓我欲罷不能。

我總是希望二者能夠調和一下,爲此我曾想過在同一個項目中同時使用這兩個框架,當然跑起來是可行的,但是總會擔心會出現什麼問題,想要徹底整合卻沒那個實力。。。

在我的不懈努力搜索之下,終於讓我找到一個項目,它可以在 spring-data-jpa 中以 freemarker 模板的形式編寫動態 sql 去執行。看起來很完美的樣子,就是還需要去學習 freemarker 而已。

但是,受此啓發,既然他拓展了 spring-data-jpa,我爲什麼不能拓展一下 mybatis 呢?於是我就編寫了一個擴展包:mybatis-jpa-support.jar
不要誤會,這個 jpa 不是指 jpa 規範,而是因爲說到 spring-data-jpa 最令人津津樂道的就是根據方法名生成 sql 語句的單表 CRUD 的操作了,所以取了這個名字。

下面說一下使用(創建項目就不貼圖了,直接貼關鍵代碼了):

首先是 pom.xml

在項目中添加以下依賴即可(需要自己下載源碼安裝到本地倉庫。。。)

        <dependency>
            <groupId>com.kfyty</groupId>
            <artifactId>mybatis-jpa-support</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

然後是實體類

package com.kfyty.mybatis.jpa.support.entity;

import lombok.Data;

import java.util.Date;

/**
 * 功能描述: 實體類
 *
 * @author [email protected]
 * @date 2019/11/16 16:41
 * @since JDK 1.8
 */
@Data
public class TestUser {
    private Integer id;
    private String name;
    private Integer age;
    private Date createTime;
    private int sortIndex;

    public TestUser() {

    }

    public TestUser(String name, Integer age) {
        this.name = name;
        this.age = age;
        this.sortIndex = age;
    }
}

Mapper 接口

package com.kfyty.mybatis.jpa.support.mapper;

import com.github.pagehelper.Page;
import com.kfyty.mybatis.jpa.support.annotation.JpaQuery;
import com.kfyty.mybatis.jpa.support.entity.TestUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 功能描述: mapper 接口
 *
 * @author [email protected]
 * @date 2019/11/16 16:39:41
 * @since JDK 1.8
 */
@Mapper
public interface TestUserMapper {
    @JpaQuery
    int insert(@Param("user") TestUser entity);

    @JpaQuery
    int insertAll(@Param("users") List<TestUser> entities);

    /**
     * pageBy 開頭或者 返回值爲 Page<T> 時自動分頁
     * @param pageNum
     * @param pageSize
     * @return
     */
    @JpaQuery
    Page<TestUser> pageByNameNotNull(int pageNum, int pageSize);

    /**
     * 自行配置 MybatisPageHelper 進行分頁
     * @param pageNum
     * @param pageSize
     * @return
     */
    @JpaQuery
    List<TestUser> findByAgeBetweenOrderByCreateTimeDesc(@Param("startAge") Integer startAge, @Param("endAge") Integer endAge, @Param("pageNum") int pageNum, @Param("pageSize") int pageSize);
}

需要提一下的是,裏面集成了 mybatis-page-helper 分頁插件(在次表示感謝),可以直接使用,當然如果想自己配置一個 Bean 的話也不會衝突。如果只想進行配置的話,可以添加如下代碼進行配置:

    @Bean("pageInterceptorProperties")
    public Properties pageProperties() {
        Properties properties = new Properties();
        properties.setProperty("supportMethodsArguments", "true");
        return properties;
    }

啓動類

package com.kfyty.mybatis.jpa.support;

import com.github.pagehelper.PageInfo;
import com.kfyty.mybatis.jpa.support.entity.TestUser;
import com.kfyty.mybatis.jpa.support.mapper.TestUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 功能描述: 啓動類
 *
 * @author [email protected]
 * @date 2019/11/16 16:35
 * @since JDK 1.8
 */
@RestController
@SpringBootApplication
public class MybatisJpaSupportDemoApplication {
    @Autowired
    private TestUserMapper testUserMapper;

    @RequestMapping("demo/insert/{name}/{age}")
    public int insert(@PathVariable("name") String name, @PathVariable("age") Integer age) {
        return testUserMapper.insert(new TestUser(name, age));
    }

    @RequestMapping("demo/insert/all/{startIndex}/{count}")
    public int insertAll(@PathVariable("startIndex") Integer startIndex, @PathVariable("count") int count) {
        List<TestUser> list = new ArrayList<>();
        for (int i = 0; i < count; i++, startIndex++) {
            list.add(new TestUser("test-" + startIndex, startIndex));
        }
        return testUserMapper.insertAll(list);
    }

    @RequestMapping("demo/page/{pageNum}/{pageSize}")
    public PageInfo page(@PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize) {
        return PageInfo.of(testUserMapper.pageByNameNotNull(pageNum, pageSize));
    }

    @RequestMapping("demo/find/age-between/{start}/{end}/{pageNum}/{pageSize}")
    public List<TestUser> findByAgeBetweenOrderByCreateTimeDesc(@PathVariable("start") int start, @PathVariable("end") int end, @PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize) {
        return testUserMapper.findByAgeBetweenOrderByCreateTimeDesc(start, end, pageNum, pageSize);
    }

    @Bean("pageInterceptorProperties")
    public Properties pageProperties() {
        Properties properties = new Properties();
        properties.setProperty("supportMethodsArguments", "true");
        return properties;
    }

    public static void main(String[] args) {
        SpringApplication.run(MybatisJpaSupportDemoApplication.class, args);
    }
}

由於這裏只涉及到了單表操作,所以不需要 Mapper.xml 文件

下面就可以啓動測試了:

-- 測試之前
mysql> select * from test_user;
Empty set (0.00 sec)

-- 測試接口: http://localhost:8080/demo/insert/1/1
mysql> select * from test_user;
+----+------+------+---------------------+------------+
| id | name | age  | create_time         | sort_index |
+----+------+------+---------------------+------------+
| 15 | 1    |    1 | 2019-12-08 14:38:01 |          1 |
+----+------+------+---------------------+------------+
1 row in set (0.00 sec)

-- 測試接口: http://localhost:8080/demo/insert/all/2/10
mysql> select * from test_user;
+----+---------+------+---------------------+------------+
| id | name    | age  | create_time         | sort_index |
+----+---------+------+---------------------+------------+
| 15 | 1       |    1 | 2019-12-08 14:38:01 |          1 |
| 16 | test-2  |    2 | 2019-12-08 14:39:08 |          2 |
| 17 | test-3  |    3 | 2019-12-08 14:39:08 |          3 |
| 18 | test-4  |    4 | 2019-12-08 14:39:08 |          4 |
| 19 | test-5  |    5 | 2019-12-08 14:39:08 |          5 |
| 20 | test-6  |    6 | 2019-12-08 14:39:08 |          6 |
| 21 | test-7  |    7 | 2019-12-08 14:39:08 |          7 |
| 22 | test-8  |    8 | 2019-12-08 14:39:08 |          8 |
| 23 | test-9  |    9 | 2019-12-08 14:39:08 |          9 |
| 24 | test-10 |   10 | 2019-12-08 14:39:08 |         10 |
| 25 | test-11 |   11 | 2019-12-08 14:39:08 |         11 |
+----+---------+------+---------------------+------------+
11 rows in set (0.00 sec)

下面測試分頁接口:

--接口: http://localhost:8080/demo/find/name-not-null/1/3
-- 日誌如下:
2019-12-08 14:42:01.418 DEBUG 6524 --- [nio-8080-exec-2] c.k.m.j.s.m.T.findByNameNotNull_COUNT    : ==>  Preparing: SELECT count(0) FROM test_user WHERE (name IS NOT NULL) 
2019-12-08 14:42:01.418 DEBUG 6524 --- [nio-8080-exec-2] c.k.m.j.s.m.T.findByNameNotNull_COUNT    : ==> Parameters: 
2019-12-08 14:42:01.419 DEBUG 6524 --- [nio-8080-exec-2] c.k.m.j.s.m.T.findByNameNotNull_COUNT    : <==      Total: 1
2019-12-08 14:42:01.421 DEBUG 6524 --- [nio-8080-exec-2] c.k.m.j.s.m.T.findByNameNotNull          : ==>  Preparing: select * from test_user where ( name is not null ) LIMIT ? 
2019-12-08 14:42:01.421 DEBUG 6524 --- [nio-8080-exec-2] c.k.m.j.s.m.T.findByNameNotNull          : ==> Parameters: 3(Integer)
2019-12-08 14:42:01.426 DEBUG 6524 --- [nio-8080-exec-2] c.k.m.j.s.m.T.findByNameNotNull          : <==      Total: 3

--接口: http://localhost:8080/demo/find/age-between/5/10/1/10
-- 日誌如下:
2019-12-08 15:07:41.874 DEBUG 5104 --- [nio-8080-exec-3] dByAgeBetweenOrderByCreateTimeDesc_COUNT : ==>  Preparing: SELECT count(0) FROM test_user WHERE age BETWEEN ? AND ? 
2019-12-08 15:07:41.874 DEBUG 5104 --- [nio-8080-exec-3] dByAgeBetweenOrderByCreateTimeDesc_COUNT : ==> Parameters: 5(Integer), 10(Integer)
2019-12-08 15:07:41.876 DEBUG 5104 --- [nio-8080-exec-3] dByAgeBetweenOrderByCreateTimeDesc_COUNT : <==      Total: 1
2019-12-08 15:07:41.876 DEBUG 5104 --- [nio-8080-exec-3] .T.findByAgeBetweenOrderByCreateTimeDesc : ==>  Preparing: select * from test_user where age between ? and ? order by create_time desc LIMIT ? 
2019-12-08 15:07:41.877 DEBUG 5104 --- [nio-8080-exec-3] .T.findByAgeBetweenOrderByCreateTimeDesc : ==> Parameters: 5(Integer), 10(Integer), 10(Integer)
2019-12-08 15:07:41.882 DEBUG 5104 --- [nio-8080-exec-3] .T.findByAgeBetweenOrderByCreateTimeDesc : <==      Total: 6

表面看起來是不是挺像那麼回事的呢?
感興趣的可以看一下:https://github.com/kfyty/mybatis-jpa-support
(PS:還在更新中。。。)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章