Mybatis 和 Solon 勾搭在一起,也是个漂亮组合

故事相关的源码

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

故事开讲

Solon 是Java世界里一个新的极易上手的Web框架,像是个清秀的年轻小伙。。。

Mybatis 是个资深的前辈,好像阿里系挺喜欢这前辈,说是喜欢它的SQL透明性(Xml sql 确实有透明性)。

以住的历史上,Mybatis 基本上是在 Spring 家族合作搞工程的。

今天主要是让 Mybatis 和 Solon 搭伙过日子试试,看看是不是合得来。

本次搭伙主要有这些挑点:

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

开始...

一、环境说明

环境 版本
IDEA 2020.2
Maven 4.0
Solon 1.5.11
mybatis-solon-plugin 1.5.11 (本例用到的关键框架)
mybatis-sqlhelper-solon-plugin 1.5.11
Mybatis 5.3.7
JDK 1.8

二、代码

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

  • (一)在 pom.xml 文件里添加依赖
<parent>
    <groupId>org.noear</groupId>
    <artifactId>solon-parent</artifactId>
    <version>1.5.11</version>
    <relativePath />
</parent>

<dependencies>
    <dependency>
        <groupId>org.noear</groupId>
        <artifactId>solon-web</artifactId>
    </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>
  • (二)修改属性文件 application.yml (添加多数据源和分布组件的配置)

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


#对应db1数据源
mybatis.db1:
    typeAliases:    #支持包名 或 类名(.class 结尾)
        - "webapp.model"
    mappers:        #支持包名 或 类名(.class 结尾)或 xml(.xml结尾)
        - "webapp.dso.mapper.AppxMapper.class"

#再定义个新配置(为了体现多数据源性 - 应该简单吧?) #对应db2数据源
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
  • (三)添加配置器(完成数据源的构建即可;看上去,挺简洁的)
@Configuration
public class Config {
    //db1 数据源(同时为默认数据源)
    @Bean(value = "db1", typed = true)
    public DataSource db1(@Inject("${test.db1}") HikariDataSource ds) {
       return ds;
    }
    
    //db2数据源
    @Bean("db2")
    public DataSource db2(@Inject("${test.db2}") HikariDataSource ds) {
       return ds;
    }
}
  • (四)添加控制器

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

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

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

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

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

}

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

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

    @Db("db2")
    Appx2Mapper appxMapper2;

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

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

}

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

/**
 * 事务演示
 *
 * @Db 可注入 Mapper, SqlSession, SqlSessionFactory, MybatisProxy
 * */
@Mapping("/tran/")
@Controller
public class TranController {
    @Inject
    AppxMapper appxMapper;

    /**
     * mybatis-solon-plugin 的事务,需要通过 MybatisProxy 发起
     *
     * solon 不目前支持注解事务,说是出于性能和细颗粒度的考虑;以及现在都流行引入消息处理事务了。
     * */
    @Db("db1")
    MybatisProxy proxy;

    @Mapping("test")
    public Object test() throws Throwable{
        return proxy.tran((s)->{
            s.result = appxMapper.appx_get();
        });
    }
}

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

@Mapping("/page/")
@Controller
public class PageController {
    @Inject
    AppxMapper appxMapper;

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

       return appxMapper.appx_get_page();
    }
}
  • (五)改写启动代码,进行插件扩展
public class DemoApp {
    public static void main(String[] args) {
        new SolonBuilder()
                .onEvent(Configuration.class, c -> { 
                    //订阅事件,添加拦截插件
                    //c.addInterceptor();
                })
                .onError((err) -> err.printStackTrace())
                .start(DemoApp.class, args);
    }
}

这里只测试了查询的方法,当然如果需要别的,可以自行添加试试。

故事结尾

所有搭伙挑战完成,OY...

posted @ 2020-08-12 14:02  带刺的坐椅  阅读(232)  评论(0编辑  收藏  举报