Mybatis 和 Solon 终于勾搭在一起了

2020-08-17  本文已影响0人  草编椅

终于说通 Solon 作者,让他为 Solon 框架添加事务注解支持了;并且把 mybatis-solon-plugin 的 @Df 注解更名为 @Db ,接地气多了(Df是什么鬼呢?新手肯定这么想...)。真是费尽了笔者的口水。。。此文主要重写《Mybatis 和 Solon 勾搭在一起》的事务部分,并优化细节。

新故事相关的源码

https://gitee.com/noear/solon_demo/tree/master/demo08.solon_mybatis_multisource

新故事开讲

Mybatis 是个资深的前辈,多年来它基本上只和 Spring 的家族企业合作。今天他尝试和年轻选手Solon组队做业务;Solon 是Java世界里一个新的极易上手的Web框架(哎,如同十八线的演员,没人知道的啦。。。但业务活也是一流的)

本次组队需要完成如下挑战:

  1. 简单的配置
  2. 多数据源支持(分区模式 和 注解模式)
  3. 事务支持
  4. 支持分页组件(这个,其实破坏了SQL的透明性......但业内很流行)

Action...

一、环境说明

环境 版本
IDEA 2020.2
Maven 4.0
Solon 1.0.15 (这是升级版啊)
mybatis-solon-plugin 1.0.15
mybatis-sqlhelper-solon-plugin 1.0.15
Mybatis 5.3.3
JDK 1.8

二、现在代码走起

新建个空白的Maven项目:solon_mybatis_multisource,下面开始操作:

<parent>
    <groupId>org.noear</groupId>
    <artifactId>solon-parent</artifactId>
    <version>1.0.15</version>
    <relativePath />
</parent>

<dependencies>
    <dependency>
        <groupId>org.noear</groupId>
        <artifactId>solon-web</artifactId>
        <type>pom</type>
    </dependency>

    <dependency>
        <groupId>org.noear</groupId>
        <artifactId>mybatis-solon-plugin</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.noear</groupId>
        <artifactId>mybatis-sqlhelper-solon-plugin</artifactId>
    </dependency>
    
    <!-- 其它依赖参考源码,不然占板面太多了  -->
</dependencies>

Solon 没有特定的数据源配置,所以随便自己起个头就可以;配置项与使用的数据源匹配即可。本例用的是HikariCP

#数据库1的配置
test.db1:
    schema: rock
    jdbcUrl: jdbc:mysql://localdb:3306/rock?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
    driverClassName: com.mysql.cj.jdbc.Driver
    username: demo
    password: UL0hHlg0Ybq60xyb

#数据库2的配置(其实我用的是同一个库)
test.db2:
    schema: rock
    jdbcUrl: jdbc:mysql://localdb:3306/rock?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
    driverClassName: com.mysql.cj.jdbc.Driver
    username: demo
    password: UL0hHlg0Ybq60xyb


#默认(这个可以换成:mybatis.db1)
mybatis:
    typeAliases:    #支持包名 或 类名(.class 结尾)
        - "webapp.model"
    mappers:        #支持包名 或 类名(.class 结尾)或 xml(.xml结尾)
        - "webapp.dso.mapper.AppxMapper.class"

#再定义个新配置(为了体现多数据源性 - 应该简单吧?)
mybatis.db2:
    typeAliases:
        - "webapp.model"
    mappers:
        - "webapp.dso.mapper.Appx2Mapper.class"


#分页组件的配置
sqlhelper:
    mybatis:
        instrumentor:
            dialect: "mysql"
            cache-instrumented-sql: true
            subquery-paging-start-flag: "[PAGING_StART]"
            subquery-paging-end-flag: "[PAGING_END]"
        pagination:
            count: true
            default-page-size: 10
            use-last-page-if-page-no-out: true
            count-suffix: _COUNT

Spring 的@MapperScan 需要多个配置器才可以完成多源,这个太烦人了;所以mybatis-solon-plugin把它调整成一个函数,故多个数据源可以整到一个配置器玩了:

@XConfiguration
public class Config {
    @XBean("db1")
    public SqlSessionFactory db1(@XInject("${test.db1}") HikariDataSource dataSource) {
        //
        //此处用了默认的配置(也可以用:mybatis.db1 进行配置)
        //
        return new MybatisAdapter(dataSource)
                .mapperScan()   //类似Spring 的 @MapperScan注解的功能
                .getFactory();
    }

    @XBean("db2")
    public SqlSessionFactory db2(
            @XInject("${test.db2}") HikariDataSource dataSource,  
            @XInject("${mybatis.db2}") Properties props) {
        //
        //此处指定了 配置 ${mybatis.db2}
        //
        return new MybatisAdapter(dataSource, props)
                .mapperScan()
                .getFactory();
    }
}

关于多数据源的分包模式示例:

/**
 * 分包模式,一开始就被会话工厂mapperScan()并关联好了
 * */
@XMapping("/demo/")
@XController
public class DemoController {
    @XInject
    AppxMapper appxMapper;      //已被db1 mapperScan 了,可直接注入

    @XInject
    Appx2Mapper appxMapper2;    //已被db2 mapperScan 了,可直接注入

    @XMapping("test")
    public AppxModel test(){
        return appxMapper.appx_get();
    }

    @XMapping("test2")
    public AppxModel test2(){
        return appxMapper2.appx_get2(48);
    }

}

关于多数据源的注解模式示例:

/**
 * 注解模式,通过@Db注入,并指定具体的会话工厂
 *
 * @Db 可注入 Mapper, SqlSession, SqlSessionFactory 类型的字段
 * */
@XMapping("/demo2/")
@XController
public class Demo2Controller {
    @Db("db1")
    AppxMapper appxMapper;     //使用@Db 指定会话工厂并注入

    @Db("db2")
    Appx2Mapper appxMapper2;

    @XMapping("test")
    public AppxModel test(){
        return appxMapper.appx_get();
    }

    @XMapping("test2")
    public AppxModel test2(){
        return appxMapper2.appx_get2(48);
    }

}

关于事务的示例:(分布式环境下,尽量用消息代理JDBC事务)

/**
 * 事务演示
 * */
@XMapping("/tran/")
@XController
public class TranController {
    @XInject
    AppxMapper appxMapper;

    /**
     * mybatis-solon-plugin 的事务,由 @XTran 注解发起(更详细的说明,以后发个新文说明)
     * */
    @XTran("db1")
    @XMapping("test")
    public Object test() throws Throwable{
        appxMapper.appx_get();
    }
}

关于多数据源事务的示例,需要用到Service层:(分布式环境下,尽量用消息代理JDBC事务)

/**
 * 多数据源事务演示
 * */
@XMapping("/tran2/")
@XController
public class Tran2Controller {
    @XInject
    AppService appService;   //这是定义的Service类,里面的函数注解了@XTran("db1")

    @XInject
    App2Service app2Service;    //同上


    /**
     * 申明这是一个多数据源的事务组(这个一般放在事务的最外层;用于管理下面的子事务)
     * */
    @XTran(group = true)
    @XMapping("test")
    public void test() throws Throwable {
        //内部申明了用db2的事务
        app2Service.add();

        //内部申明了用db1的事务
        appService.add();
    }
}

关于分页的示例:(本案用的是sqlhelper)

@XMapping("/page/")
@XController
public class PageController {
    @XInject
    AppxMapper appxMapper;

    @XMapping("test")
    public Object test() throws Throwable{
        SqlPaginations.preparePagination(2,2);

       return appxMapper.appx_get_page();
    }
}

故事结尾

加了事务注解后,终于优雅了。。。所有组队挑战全部完成,OY...

上一篇下一篇

猜你喜欢

热点阅读