Tkmybatis快速入手

Tkmybatis

案例码云地址:使用 git clone 即可查看
https://gitee.com/JavaBigDataStudy/tk-mybatis-jpa-demo.git

让你远离sql语句的Mybatis工具==>去除mapper.xml

只需三步即可使用单表常用操作:导包==》继承==》在启动类中设置扫描 ==>使用

通过我们去调用它封装的各种方法来实现sql语句的效果。对于单表查询不需要写SQL语句,这样就不用像mybatis那样每次写一个接口就要写一条sql语句

特点:

Tkmybatis是基于Mybatis框架开发的一个工具,通过调用它提供的方法实现对单表的数据操作,不需要写任何sql语句,这极大地提高了项目开发效率。

Tkmybatis使用 :

项目结构:
在这里插入图片描述

1、pom.xml添加依赖

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <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>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
     </dependency>
</dependencies>

2、创建数据库表对应实体类对象

DROP TABLE IF EXISTS category;
CREATE TABLE category (
  category_id   INT PRIMARY KEY,
  category_name VARCHAR (50) NOT NULL,
  description   VARCHAR (100)
);

DELETE FROM category;
INSERT INTO category (category_id, category_name, description) VALUES
  (1, 'Beverages', 'test'),
  (2, 'Condiments', 'test'),
  (3, 'Oil', 'test');
@Data
@Table(name = "category")
public class Category {
    @Id
    @Column(name = "category_id")
    private Integer categoryID;
    private String categoryName;
    private String description;
}
实体类中,使用了以下注解:

@Table
描述数据库表信息,主要属性有name(表名)、schema、catalog、uniqueConstraints等。

@Id
指定表主键字段,无属性值。

@Column
描述数据库字段信息,主要属性有name(字段名)、columnDefinition、insertable、length、nullable(是否可为空)、precision、scale、table、unique、updatable等。

@ColumnType
描述数据库字段类型,可对一些特殊类型作配置,进行特殊处理,主要属性有jdbcType、column、typeHandler等。

@Transient
标识该属性不进行数据库持久化操作,无属性。

还有其他相关注解,如@ColumnResult、@JoinColumn、@OrderBy、@Embeddable等,可以做简单解一下,用的不多。

@Data
lombok插件用于简化代码的注解,无需写get set 等代码。

3、Mapper数据库操作接口

只需要继承tk.mybatis.mapper.common.Mapper即可。

4、Tkmybatis数据库操作方法API

增
Mapper.insert(record);

保存一个实体,null的属性也会保存,不会使用数据库默认值

Mapper.insertSelective(record);

保存一个实体,null的属性不会保存,会使用数据库默认值

删
Mapper.delete(record);

根据实体属性作为条件进行删除,查询条件使用等号

Mapper.deleteByExample(example)

根据Example条件删除数据

Mapper.deleteByPrimaryKey(key)

根据主键字段进行删除,方法参数必须包含完整的主键属性

改
Mapper.updateByExample(record, example)

根据Example条件更新实体`record`包含的全部属性,null值会被更新

Mapper.updateByExampleSelective(record, example)

根据Example条件更新实体`record`包含的不是null的属性值

Mapper.updateByPrimaryKey(record)

根据主键更新实体全部字段,null值会被更新

Mapper.updateByPrimaryKeySelective(record)

根据主键更新属性不为null的值

查
Mapper.select(record)

根据实体中的属性值进行查询,查询条件使用等号

Mapper.selectAll()

查询全部结果

Mapper.selectByExample(example)

根据Example条件进行查询

Mapper.selectByExampleAndRowBounds(example, rowBounds)

根据example条件和RowBounds进行分页查询

Mapper.selectByPrimaryKey(key)

根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号

Mapper.selectByRowBounds(record, rowBounds)

根据实体属性和RowBounds进行分页查询

Mapper.selectCount(record)

根据实体中的属性查询总数,查询条件使用等号

Mapper.selectCountByExample(example)

根据Example条件进行查询总数

Mapper.selectOne(record)

根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号

Example条件 (自定义查询条件)

 //注意:(addEqualTo)这里的userId是映射的实体类。
    @Test
    public void selectAllTest2() {
        Example example = new Example(Category.class);
        example.createCriteria()
                .andEqualTo("categoryID",1)
                .andEqualTo("categoryName","Beverages");

        List<Category> categories = categoryDao.selectByExample(example);
        System.out.println(categories);
        assertEquals(true, categories.size() > 0);
    }

    //注意:(addCondition)这里的user_id是数据库的字段。即where后面的条件。应该写sql语句。
    @Test
    public void selectAllTest3() {
        Example example = new Example(Category.class);
        example.createCriteria()
                .andCondition("category_id=",1)
                .andCondition("category_name=","Beverages");

        List<Category> categories = categoryDao.selectByExample(example);
        System.out.println(categories);
        assertEquals(true, categories.size() > 0);
    }

Example条件基本涵盖了常用的sql条件,并且支持使用原生sql语句字符串查询。

拓展-复杂查询
方式1:

public class ComplexTKMapperTest {

    @Autowired
    CategoryDao categoryDao;

    @Test
    public void testNestConditions(){

        Example e = new Example(Category.class);
        Example.Criteria c = e.createCriteria();

        //关键字查询部分
        String keyword = "key";
        if (!StringUtils.isEmpty(keyword)) {
            c.orEqualTo("categoryName", keyword)
                    .orEqualTo("categoryID",keyword)
                    .orEqualTo("description",keyword);
        }
        //部门查询部门
        Example.Criteria criteria = e.createCriteria();
        criteria.andEqualTo("categoryID", "1112");
        e.and(criteria);

        List<Category> users = categoryDao.selectByExample(e);
    }
}

执行的sql为:
SELECT category_id, category_name, description FROM category WHERE (
category_name = ?
OR category_id = ?
OR description = ? ) AND (category_id = ?)

方式2

 @Test
    public void testNestConditions2(){

        Weekend<Category> weekend = new Weekend<>(Category.class);
        //关键字查询部分
        String keyword = "key";
        WeekendCriteria<Category, Object> keywordCriteria = weekend.weekendCriteria();
        if (!StringUtils.isEmpty(keyword)) {
            keywordCriteria.orLike(Category::getCategoryName, keyword).
                    orLike(Category::getCategoryID, keyword)
                    .orLike(Category::getDescription, keyword);
            //此处不需要再用下面这一句了,不然上面这个条件组合会重复一次
            //weekend.and(keywordCriteria)
        }

        //部门查询部分
        Example example = new Example(Category.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("categoryID", "i222");
        weekend.and(criteria);
        List<Category> users = categoryDao.selectByExample(weekend);
    }

其中Weekend是高版本的通用mapper版本才有,而且需要java8语法支持。
在这里插入图片描述

执行效果如下图:
在这里插入图片描述

总结下来,就是

每个条件组合(a/b/c) (d)各自创建自己的cirteria,再用and或者or方法去连接

结语

Tkmybatis极大地提高了我们对单表数据库操作的开发效率,可以在实际项目开发中推荐使用。


拓展部分:

源码的简单分析,大家可以自己基于这个原理自定义特定的需求

此框架为我们实现这些功能所有的改动都在Mapper层面,所有的Mapper都继承了tk.mybatis.mapper.common.Mapper

public interface WorkerMapper extends Mapper {}
Mapper接口的声明如下,可以看到Mapper接口实现了所有常用的方法

public interface Mapper<T> extends BaseMapper<T>, ExampleMapper<T>, RowBoundsMapper<T>, Marker {

}

看一下完整的UML图,太大了,可以用新窗口打开,放大之后再看
在这里插入图片描述

这里选择一个接口:SelectOneMapper接口,对于源码进行简单分析,此接口声明如下:

public interface SelectOneMapper<T> {

    /** * 根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号 * * @param record * @return */
    @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
    T selectOne(T record);

}

@SelectProvider是mybatis3之后提供的,用于灵活的设置sql来源,这里设置了服务提供类和方法,但这个库并没有直接用method指定的方法来返回sql,而是在运行时进行解析的,代码如下

public class BaseSelectProvider extends MapperTemplate {

    public String selectOne(MappedStatement ms) {
        Class<?> entityClass = getEntityClass(ms);
        //修改返回值类型为实体类型
        setResultType(ms, entityClass);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.selectAllColumns(entityClass));
        sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
        sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty()));
        return sql.toString();
    }
}

到这里我们就大概知道了这个库为我们提供便利的原理了,总的来说就是这个库帮我们提供了对表的基本操作的sql,帮我们省了很多工作量,而且维护起来也很方便,否则我们的xml文件动不动就几百行甚至上千行

对源码的探索不能到这里停止,最起码要分析到与另一个框架的整合点

我们知道,mybatis的mapper接口是在启动的时候被框架以JdkProxy的形式封装了的,具体对应的类是MapperFactoryBean,这个类中有一个checkDaoConfig()方法,是从父类继承并重写了该方法,继承结构如下

MapperFactoryBean -> SqlSessionDaoSupport -> DaoSupport
在这里插入图片描述
这里的DaoSupport就是spring提供的Dao的抽象,代码如下

public abstract class DaoSupport implements InitializingBean {

// spring 完成属性设置后会调用此方法
    @Override
    public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
        // 这里提供了接口供子类去实现
        checkDaoConfig();

        // Let concrete implementations initialize themselves.
        try {
            initDao();
        }
        catch (Exception ex) {
            throw new BeanInitializationException("Initialization of DAO failed", ex);
        }
    }

    protected abstract void checkDaoConfig() throws IllegalArgumentException;

    protected void initDao() throws Exception {
    }

}

框架自定义的MapperFactoryBean重写了checkDaoConfig()方法,完成对所有sql语句的设置,代码如下

@Override
    protected void checkDaoConfig() {
        super.checkDaoConfig();
        //通用Mapper
        if (mapperHelper.isExtendCommonMapper(getObjectType())) {
        //这里去处理该类所对应的MappedStatement,封装在helper类中处理
            mapperHelper.processConfiguration(getSqlSession().getConfiguration(), getObjectType());
        }
    }

MapperHelper的processConfiguration方法如下

public void processConfiguration(Configuration configuration, Class<?> mapperInterface) {
        String prefix;
        if (mapperInterface != null) {
            prefix = mapperInterface.getCanonicalName();
        } else {
            prefix = "";
        }
        for (Object object : new ArrayList<Object>(configuration.getMappedStatements())) {
            if (object instanceof MappedStatement) {
                MappedStatement ms = (MappedStatement) object;
                //检查这个MappedStatement是否属于此映射对象
                if (ms.getId().startsWith(prefix) && isMapperMethod(ms.getId())) {
                    if (ms.getSqlSource() instanceof ProviderSqlSource) {
                       //去设置该statement的sql语句
                        setSqlSource(ms);
                    }
                }
            }
        }
    }

设置sql的逻辑,提供了几种不同类型的sqlsource

在这里插入图片描述
在这里插入图片描述

到这里整个sql的获取流程就分析完了。大家可以根据实际需求拓展。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder_Boy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值