初识 tk.mybatis.mapper 通用mapper

在博客园发表Mybatis Dynamic Query后,一位园友问我知不知道通用 mapper,仔细去找了一下,还真的有啊,比较好的就是 abel533 写的tk.mybatis.mapper
本次例子地址:https://github.com/wz2cool/tk-mybatis-demo

传统 Mybatis 用法

Spring boot

引用基本的 jar 到 pom

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.4</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>1.5.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>1.5.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>

sql 数据准备

DROP TABLE IF EXISTS category;
CREATE TABLE category (
  category_id   INT PRIMARY KEY,
  category_name VARCHAR (50) NOT NULL,
  description   VARCHAR (100)
);
DROP TABLE IF EXISTS product;
CREATE TABLE product (
  product_id    INT PRIMARY KEY auto_increment,
  category_id   INT NOT NULL,
  product_name  VARCHAR (50) NOT NULL,
  price         DECIMAL
);
DELETE FROM category;
INSERT INTO category (category_id, category_name, description) VALUES
  (1, 'Beverages', 'test'),
  (2, 'Condiments', 'test'),
  (3, 'Oil', 'test');
  DELETE FROM product;
INSERT INTO product (product_id, category_id, product_name, price) VALUES
  (1, 1, 'Northwind Traders Chai', 18.0000),
  (2, 2, 'Northwind Traders Syrup', 7.5000),
  (3, 2, 'Northwind Traders Cajun Seasoning', 16.5000),
  (4, 3, 'Northwind Traders Olive Oil', 16.5000),
  (5, 3, 'Northwind Traders Olive Oil2', 16.5000);

entity

public class Product {
    private Integer productID;
    private String productName;
    private BigDecimal price;
    private Integer categoryID;
    // get/set...
}

@Table(name = "category")
public class Category {
@Id
@Column(name = "category_id")
private Integer categoryID;
private String categoryName;
private String description;
// get /set...
}

Dao

这里的 ProductDao 是传统的 mybatis 的用法。

@Mapper
public interface ProductDao {
    List<Product> getProducts();
}

mapper

传统 mybatis 我们必须有个 xml 文件和 Dao 对应起来, tk.maybatis.mapper 无需此文件。

<mapper namespace="com.github.wz2cool.demo.tk.mybatis.mapper.ProductDao">
    <select id="getProducts" resultType="com.github.wz2cool.demo.tk.mybatis.model.entity.table.Product">
        SELECT * FROM product
    </select>
</mapper>

设置扫描包

@SpringBootApplication
@MapperScan(basePackages = "com.github.wz2cool.demo.tk.mybatis.mapper")
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

application.properies

注意这里的配置只是针对我们传统 mybatis 配置,对于 tk.maybatis.mapper 可以省略这里的配置。

mybatis.type-aliases-package=com.github.wz2cool.demo.tk.mybatis.mapper
mybatis.mapper-locations=classpath:com.github.wz2cool.demo.tk.mybatis.mapper/*.xml

测试

我们可以简单调用一下

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = TestApplication.class)
public class SimpleTest {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> ProductDao productDao;

<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testSelect</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception {
    List&lt;Product&gt; productList = productDao.getProducts();
    assertEquals(<span class="hljs-literal">true</span>, productList.size() &gt; <span class="hljs-number">0</span>);
}

}

我们可以看到输出结果,基本上就通了

==>  Preparing: SELECT * FROM product 
==> Parameters: 
<==    Columns: PRODUCT_ID, CATEGORY_ID, PRODUCT_NAME, PRICE
<==        Row: 1, 1, Northwind Traders Chai, 18.0000
<==        Row: 2, 2, Northwind Traders Syrup, 7.5000
<==        Row: 3, 2, Northwind Traders Cajun Seasoning, 16.5000
<==        Row: 4, 3, Northwind Traders Olive Oil, 16.5000
<==        Row: 5, 3, Northwind Traders Olive Oil2, 16.5000
<==      Total: 5

tk.mybatis.mapper 用法

添加引用

需要多添加两个引用 (ps: 曾经少了一个 mapper-spring-boot-starter, 报错死活找不到为什么 --!!!)

<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper</artifactId>
    <version>3.4.2</version>
</dependency>
<!--mapper-->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>1.1.3</version>
</dependency>

继承通用 mapper

嗯 是的没有 xml 文件。

public interface CategoryDao extends Mapper<Category> {
}

测试调用

dao 里面自带很多方法,比如 selectAll(), insert().

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = TestApplication.class)
public class SimpleTkMapperTest {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> CategoryDao categoryDao;

<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">selectAllTest</span><span class="hljs-params">()</span> {
    List&lt;Category&gt; categories = categoryDao.selectAll();
    assertEquals(<span class="hljs-literal">true</span>, categories.size() &gt; <span class="hljs-number">0</span>);
}

<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">insertTest</span><span class="hljs-params">()</span> {
    <span class="hljs-type">Category</span> <span class="hljs-variable">newCategory</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Category</span>();
    newCategory.setCategoryID(<span class="hljs-number">1000</span>);
    newCategory.setCategoryName(<span class="hljs-string">"test"</span>);
    newCategory.setDescription(<span class="hljs-string">"for test"</span>);
    <span class="hljs-type">int</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> categoryDao.insert(newCategory);
    assertEquals(<span class="hljs-number">1</span>, result);
}

}

输出结果

==>  Preparing: SELECT category_id,category_name,description FROM category 
==> Parameters: 
<==    Columns: CATEGORY_ID, CATEGORY_NAME, DESCRIPTION
<==        Row: 1, Beverages, test
<==        Row: 2, Condiments, test
<==        Row: 3, Oil, test
<==      Total: 3

==> Preparing: INSERT INTO category ( category_id,category_name,description ) VALUES( ?,?,? )
==> Parameters: 1000(Integer), test(String), for test(String)
<== Updates: 1

tk.mybatis.mapper 初步使用感受

优势

  1. 无需 xml 文件和 Dao 对应。
  2. 无需指定 xml 文件位置(因为就没有 xml 文件)。
  3. 自带多种常用方法。

困惑(仅代表个人观点)

  1. 自带的方法多但是有些方法理解很晦涩,比如 deleteByExample(Object var1),这里给一个 object 我都不知道要填什么,是填写主键呢还是这个实体呢?(后来了解其实 example 应该是一个筛选条件)

tk.mybatis.mapper(Criteria) 筛选

在理解 Example 以后,就开始了解了 Criteria 筛选,当然 Example 还是可以做排序的。
来看看 tk.mybatis.mapper 筛选是如何做的

@Test
public void selectByExampleTest() {
    Example example = new Example(Category.class);
    Example.Criteria criteria = example.createCriteria();
    criteria.andEqualTo("categoryID", 1);
    criteria.orEqualTo("categoryID", 2);
    categoryDao.selectByExample(example);
}

输出结果

==>  Preparing: SELECT category_id,category_name,description FROM category WHERE ( category_id = ? or category_id = ? ) 
==> Parameters: 1(Integer), 2(Integer)
<==    Columns: CATEGORY_ID, CATEGORY_NAME, DESCRIPTION
<==        Row: 1, Beverages, test
<==        Row: 2, Condiments, test
<==      Total: 2

结束

这个只是我初次使用 tk.mybatis.mapper 确实不错,可以减少工作量,好像还有可以生成 Dao 和 mapper 的工具,这个我以后再试试看。

要有自己的 Mapper

看了 tk.mybatis.mapper 以后,觉得通用 mapper 也应该加入到 Mybatis Dynamic Query 中去,当然实现可能有点不一样。

关于 tk.mybatis.mapper 问题

这里真的想问问园友了

  1. tk.mybatis.mapper 支持多表筛选么(join),我自己好像没有找到。
  2. tk.mybatis.mapper 支持组么,就是类似于 (id > 1 and id < 5) and price = 10.

关注我 ##

最后大家可以关注我和 Mybatis-Dynamic-query 项目 _
Follow @wz2cool Star Fork