手机版 欢迎访问it开发者社区(www.mfbz.cn)网站

当前位置: > 开发

牛叉了-arthas 热更新 mybatis mapper xml

时间:2021/5/10 23:39:20|来源:|点击: 次

测试环境能够热更新class 能否热更新mapper xml? arthas 群有同学提了这样的一个需求,必须满足满足
arthas-idea-plugin 2.8 版本 https://plugins.jetbrains.com/plugin/13581-arthas-idea

1、基本思路

1.1 流程图

在这里插入图片描述

1.2 实现效果

 echo `redis-cli -h '127.0.0.1' -p 6379  get arthasIdeaPluginRedefineCacheKey_e00b5a9e-d926-43c6-8b3f-5790841557ed`  | base64 --decode >arthas-idea-plugin-mybatis-mapper-xml-reload.sh;chmod a+x arthas-idea-plugin-mybatis-mapper-xml-reload.sh;./arthas-idea-plugin-mybatis-mapper-xml-reload.sh;
./arthas-idea-plugin-mybatis-mapper-xml-reload.sh: line 13: /Users/wangji/opt/arthas/mybatis/mapper/UserDoMapper.xml: Permission denied
************************************************************************************************************************
* arthas idea plugin begin;start script path: /Users/wangji/opt/arthas/arthas-idea-plugin-mybatis-mapper-xml-reload.sh *
************************************************************************************************************************


decode base64 text to path /Users/wangji/opt/arthas/mybatis/mapper/UserDoMapper.xml

[INFO] JAVA_HOME: /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home
* [1]: 98083 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [2]: 98051 org.jetbrains.jps.cmdline.Launcher
  [3]: 98052 com.intellij.idea.Main
  [4]: 98167 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [5]: 98567 org.jetbrains.jps.cmdline.Launcher
  [6]: 98568 com.boot.mybatis.mybatisdemo.MybatisDemoApplication
  [7]: 96571 org.jetbrains.kotlin.daemon.KotlinCompileDaemon
  [8]: 98076 org.jetbrains.jps.cmdline.Launcher
  [9]: 96412

 请手动选择进程或者idea 预先配置jps -l 工程名称自动执行

6
******************************************************************
* first: get spring static spring context class1oader hash value *
******************************************************************

arthas start command :/Users/wangji/opt/arthas/as.sh --height 100 --width 200 --select 98568  -c "sc -d com.boot.mybatis.mybatisdemo.common.ApplicationContextProvider"  | tee /Users/wangji/opt/arthas/classLoaderHashValue.out
Arthas script version: 3.5.0
[INFO] JAVA_HOME: /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home
[INFO] Process 98568 already using port 3658
[INFO] Process 98568 already using port 8563
Arthas home: /Users/wangji/opt/arthas
Calculating attach execution time...
Attaching to 98568 using version /Users/wangji/opt/arthas...

real	0m0.236s
user	0m0.419s
sys	0m0.056s
Attach success.
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'


wiki       https://arthas.aliyun.com/doc
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
version    3.5.0
main_class com.boot.mybatis.mybatisdemo.MybatisDemoApplication
pid        98568
time       2021-05-10 22:00:59

[arthas@98568]$ sc -d com.boot.mybatis.mybatisdemo.common.ApplicationContextProvider | plaintext
 class-info        com.boot.mybatis.mybatisdemo.common.ApplicationContextProvider
 code-source       /Users/wangji/Documents/project/mybatis-demo/target/classes/
 name              com.boot.mybatis.mybatisdemo.common.ApplicationContextProvider
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       ApplicationContextProvider
 modifier          public
 annotation        org.springframework.stereotype.Component
 interfaces        org.springframework.context.ApplicationContextAware
 super-class       +-java.lang.Object
 class-loader      +-sun.misc.Launcher$AppClassLoader@18b4aac2
                     +-sun.misc.Launcher$ExtClassLoader@5762806e
 classLoaderHash   18b4aac2

Affect(row-cnt:1) cost in 22 ms.
[arthas@98568]$

**************************************************************
* last: invoke spring bean to reload mybatis mapper xml file *
**************************************************************

arthas start command :/Users/wangji/opt/arthas/as.sh --height 100 --width 200 --select 98568  -c "ognl -x 3 '#springContext=@com.boot.mybatis.mybatisdemo.common.ApplicationContextProvider@context,#springContext.getBean("mybatisMapperXmlFileReloadService").reloadAllSqlSessionFactoryMapper("/Users/wangji/opt/arthas/mybatis/mapper/UserDoMapper.xml")' -c 18b4aac2"  | tee /Users/wangji/opt/arthas/mybatisMapperXmlReloadResult.out
Arthas script version: 3.5.0
[INFO] JAVA_HOME: /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home
[INFO] Process 98568 already using port 3658
[INFO] Process 98568 already using port 8563
Arthas home: /Users/wangji/opt/arthas
Calculating attach execution time...
Attaching to 98568 using version /Users/wangji/opt/arthas...

real	0m0.212s
user	0m0.383s
sys	0m0.051s
Attach success.
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'


wiki       https://arthas.aliyun.com/doc
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
version    3.5.0
main_class com.boot.mybatis.mybatisdemo.MybatisDemoApplication
pid        98568
time       2021-05-10 22:00:59

Mapper("/Users/wangji/opt/arthas/mybatis/mapper/UserDoMapper.xml")' -c 18b4aac2 | plaintextontextProvider@context,#springContext.getBean("mybatisMapperXmlFileReloadService").reloadAllSqlSessionFactory
@Boolean[true]
[arthas@98568]$
********************************************************
* arthas idea plugin mybatis mapper xml reload success *
********************************************************

2、解决的问题

  • 基于static spring context 调用bean 方法传递 路径,提供一个 spring bean 去执行热更新
  • 需要全局的自动化,解决classloader的传递问题,需要脚本去解决。

基于这样的一个思路,提供一个bean 一个路径即可
com.github.wangji92.mybatis.reload.core.MybatisMapperXmlFileReloadService#reloadAllSqlSessionFactoryMapper

详细代码地址可以参考:https://github.com/WangJi92/mybatis-mapper-reload-spring-boot-start
简单的实现有bug 欢迎提交pr

public boolean reloadAllSqlSessionFactoryMapper(String mapperFilePath) {
        if (CollectionUtils.isEmpty(sqlSessionFactoryList)) {
            log.warn("not find SqlSessionFactory bean");
            return false;
        }

        Path path = Paths.get(mapperFilePath);
        if (!Files.exists(path)) {
            log.warn("mybatis reload mapper xml not exist ={}", mapperFilePath);
            return false;
        }

        AtomicBoolean result = new AtomicBoolean(true);

        sqlSessionFactoryList.parallelStream().forEach(sqlSessionFactory -> {
            Configuration configuration = sqlSessionFactory.getConfiguration();
            if (!this.removeMapperCacheAndReloadNewMapperFile(path, configuration)) {
                log.warn("reload new mapper file fail path={}", path.toString());
                result.set(false);
            } else {
                log.info("reload new mapper file success path={}", path.toString());
            }
        });
        return result.get();
 }

3、配置

3.1 配置static spring context

https://www.yuque.com/wangji-yunque/ikhsmq/ugrc8n#4XuEK 详情查看这里。
在这里插入图片描述

3.2 配置 reload mapper service bean name method name

在这里插入图片描述

4、测试

demo link: https://github.com/WangJi92/mybatis-log-demo

4.1 old

<select id="selectByExample" parameterType="com.boot.mybatis.mybatisdemo.model.dataobject.UserDoExample" resultMap="BaseResultMap">
    select
    <if test="distinct">
      distinct
    </if>
    <include refid="Base_Column_List" />
    from user
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
  </select>

在这里插入图片描述

4.2 选择修改的xml 文件

4.2.1 构建脚本

在这里插入图片描述

4.2.2 修改的xml

<select id="selectByExample" parameterType="com.boot.mybatis.mybatisdemo.model.dataobject.UserDoExample" resultMap="BaseResultMap">
    select
    name
    from user
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
  </select>

4.2.3 执行后的结果

在这里插入图片描述

在这里插入图片描述

Copyright © 2002-2019 某某自媒体运营 版权所有