baomidou / mybatis-plus

An powerful enhanced toolkit of MyBatis for simplify development
https://baomidou.com
Apache License 2.0
16.35k stars 4.31k forks source link

Spring-Native 打包后运行报错,请问有这方面的例子吗? #4028

Closed sk142857 closed 1 year ago

sk142857 commented 2 years ago
06:39:40.950 [main] INFO org.springframework.boot.SpringApplication - AOT mode enabled,
2021-11-03 06:39:40.964  INFO 1 --- [           main] o.s.nativex.NativeListener               : This application is bootstrapped with code generated with Spring AOT,
,
  .   ____          _            __ _ _,
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \,
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \,
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) ),
  '  |____| .__|_| |_|_| |_\__, | / / / /,
 =========|_|==============|___/=/_/_/_/,
 :: Spring Boot ::            (v2.6.0-RC1),
,
2021-11-03 06:39:40.966  INFO 1 --- [           main] c.b.m.s.q.QuickstartApplication          : Starting QuickstartApplication using Java 11.0.13 on 1a65476b9eca with PID 1 (/workspace/com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication started by cnb in /workspace),
2021-11-03 06:39:40.966 DEBUG 1 --- [           main] c.b.m.s.q.QuickstartApplication          : Running with Spring Boot v2.6.0-RC1, Spring v5.3.12,
2021-11-03 06:39:40.966  INFO 1 --- [           main] c.b.m.s.q.QuickstartApplication          : No active profile set, falling back to default profiles: default,
2021-11-03 06:39:40.968 ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application run failed,
,
java.lang.ExceptionInInitializerError: null,
    at org.mybatis.spring.mapper.MapperScannerConfigurer.postProcessBeanDefinitionRegistry(MapperScannerConfigurer.java:357) ~[com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication:2.0.6],
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[na:na],
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:142) ~[na:na],
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) ~[na:na],
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) ~[na:na],
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[na:na],
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:719) ~[com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication:2.6.0-RC1],
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:401) ~[com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication:2.6.0-RC1],
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) ~[com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication:2.6.0-RC1],
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication:2.6.0-RC1],
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1279) ~[com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication:2.6.0-RC1],
    at com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication.main(QuickstartApplication.java:12) ~[com.baomidou.mybatisplus.samples.quickstart.QuickstartApplication:na],
Caused by: org.apache.ibatis.logging.LogException: Error creating logger for logger org.mybatis.spring.mapper.ClassPathMapperScanner.  Cause: java.lang.NullPointerException,
    at org.apache.ibatis.logging.LogFactory.getLog(LogFactory.java:54) ~[na:na],
    at org.apache.ibatis.logging.LogFactory.getLog(LogFactory.java:47) ~[na:na],
    at org.mybatis.logging.LoggerFactory.getLogger(LoggerFactory.java:32) ~[na:na],
    at org.mybatis.spring.mapper.ClassPathMapperScanner.<clinit>(ClassPathMapperScanner.java:58) ~[na:na],
    ... 12 common frames omitted,
Caused by: java.lang.NullPointerException: null,
    at org.apache.ibatis.logging.LogFactory.getLog(LogFactory.java:52) ~[na:na],
    ... 15 common frames omitted,
xyz327 commented 2 years ago

不支持反射吧。 我记得是需要配置文件指定下要反射类信息的

sk142857 commented 2 years ago

不支持反射吧。 我记得是需要配置文件指定下要反射类信息的

是的呢!自己一个个去找太麻烦了。

xyz327 commented 2 years ago

https://github.com/mybatis/mybatis-3/issues/1552 是 mybatis 不支持吧

sk142857 commented 2 years ago

mybatis/mybatis-3#1552 是 mybatis 不支持吧

这个也看过,好像是的,就是不知道怎么解决。mybatis 不能用,微服务项目就暂时没法用 spring-native了。有合适的解决方案吗?

liuzhou12315 commented 2 years ago

@Lee27149 跟你一样的报错,请问你解决了吗? 报错的这个地方我看了下源码,应该不能通过配置反射信息来解决吧 因为它本身就是动态传参来创建的 配置不了, org.apache.ibatis.logging.LogFactory中: public static Log getLog(String logger) { try { return logConstructor.newInstance(logger); // 这里报错 } catch (Throwable t) { throw new LogException("Error creating logger for logger " + logger + ". Cause: " + t, t); } } 。。。。 private static void setImplementation(Class<? extends Log> implClass) { try { Constructor<? extends Log> candidate = implClass.getConstructor(String.class); Log log = candidate.newInstance(LogFactory.class.getName()); if (log.isDebugEnabled()) { log.debug("Logging initialized using '" + implClass + "' adapter."); } logConstructor = candidate; // 就是因为这个反射没成功,logConstructor才空指针 } catch (Throwable t) { throw new LogException("Error setting Log implementation. Cause: " + t, t); } }

liuzhou12315 commented 2 years ago

@Lee27149 我的解决办法是使用svm的targetClass, substitue,替代上面那段源码的getLog方法,亲测可行

sk142857 commented 2 years ago

@Lee27149 我的解决办法是使用svm的targetClass, substitue,替代上面那段源码的getLog方法,亲测可行

解决了?

kamjin1996 commented 2 years ago

很可惜几乎所有的库或多或少都用到了反射 不过graalvm好像有工具可以生成配置文件

yinjunfeng commented 2 years ago

这个自定义 reflect-config.json, 增加 { "name": "org.apache.ibatis.logging.slf4j.Slf4jImpl", "allDeclaredFields": true, "allDeclaredConstructors": true, "allDeclaredMethods": true, "allPublicMethods": true, "allDeclaredClasses": true }, { "name": "org.slf4j.Marker", "allDeclaredFields": true, "allDeclaredConstructors": true, "allDeclaredMethods": true, "allPublicMethods": true, "allDeclaredClasses": true } 配置就可以了

linghengqian commented 2 years ago

这个自定义 reflect-config.json, 增加 { "name": "org.apache.ibatis.logging.slf4j.Slf4jImpl", "allDeclaredFields": true, "allDeclaredConstructors": true, "allDeclaredMethods": true, "allPublicMethods": true, "allDeclaredClasses": true }, { "name": "org.slf4j.Marker", "allDeclaredFields": true, "allDeclaredConstructors": true, "allDeclaredMethods": true, "allPublicMethods": true, "allDeclaredClasses": true } 配置就可以了

Hi, I want to ask if you can explain it in detail? It would be great if you can submit a DEMO to https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples .

linghengqian commented 2 years ago

mybatis/mybatis-3#1552 是 mybatis 不支持吧

这个也看过,好像是的,就是不知道怎么解决。mybatis 不能用,微服务项目就暂时没法用 spring-native了。有合适的解决方案吗?

This problem has been preliminarily solved by Mybatis maintainer. Would you like to try integration in Mybatis Plus at an early stage? Of course, XML files are currently supported now. Related to this link is

tanoak10 commented 2 years ago

https://github.com/mybatis/mybatis-3/pull/1611 mybatis 新版本是支持得

linghengqian commented 2 years ago

https://github.com/mybatis/mybatis-3/pull/1611 mybatis 新版本是支持得

No, to this day Mybatis full support for GraalVM is still a problem. The issue is on it.

ccwxl commented 2 years ago

https://github.com/kazuki43zoo/mybatis-spring-native

ccwxl commented 2 years ago

和spring集成只能手动集成, 自己集成mybati-plus 的 SQLSessionFactory等. 这样是可以的. 但是使用wrapper的时候有一些反射类型转换的问题. 当前版本的graalvm还不支持. 只能等等了. 或者mp改实现方式

linghengqian commented 2 years ago

Such as https://github.com/spring-projects-experimental/spring-native/issues/404#issuecomment-1026324672, Mybatis officially supports Spring Native, and I think it's easier than ever for us to move this process forward.

ccwxl commented 2 years ago

mp中的LambdaQuery会动态生成Lambda类. 这些类会被反射调用其writeReplace

/**
     * 该缓存可能会在任意不定的时间被清除
     *
     * @param func 需要解析的 lambda 对象
     * @param <T>  类型,被调用的 Function 对象的目标类型
     * @return 返回解析后的结果
     */
    public static <T> LambdaMeta extract(SFunction<T, ?> func) {
        // 1. IDEA 调试模式下 lambda 表达式是一个代理
        if (func instanceof Proxy) {
            return new IdeaProxyLambdaMeta((Proxy) func);
        }
        // 2. 反射读取
        try {
            Method method = func.getClass().getDeclaredMethod("writeReplace");
            return new ReflectLambdaMeta((SerializedLambda) ReflectionKit.setAccessible(method).invoke(func));
        } catch (Throwable e) {
            // 3. 反射失败使用序列化的方式读取
            return new ShadowLambdaMeta(com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda.extract(func));
        }
    }

这些类如何在编译期间被graalvm 构建? 类似于

Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: SerializationConstructorAccessor class not found for declaringClass: cn.xxx.platform.xxx.web.TestController$$Lambda$8344ef4bacd60313614e73f8916982c06ef20243 (targetConstructorClass: java.lang.Object). Usually adding cn.xxx.platform.xxx.web.TestController$$Lambda$8344ef4bacd60313614e73f8916982c06ef20243 to serialization-config.json fixes the problem.
        at com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89) ~[na:na]
ccwxl commented 2 years ago

https://github.com/quarkiverse/quarkus-mybatis/issues/184 这个问题已经解决. 对与spring native 可以增加serialization-config.json 类似于:


{
  "types": [
    {
      "name": "com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda"
    },
    {
      "name": "com.baomidou.mybatisplus.core.toolkit.support.SFunction"
    }
  ],
  "lambdaCapturingTypes": [
    {
      "name": "cn.nvriot.platform.geocoding.web.TestController"
    }
  ]
}
``` 可以解决LambdaMeta 的问题. 
zxuanhong commented 1 year ago

@siaron 不知道能否提供一个完整的案例,迫切希望能收到你的回答。

linghengqian commented 1 year ago
ccwxl commented 1 year ago

quarkiverse/quarkus-mybatis#184

https://github.com/quarkiverse/quarkus-mybatis/issues/184

看下这个issue. 里面有demo. 不过是quarkus. springboot3.0 还没测试过.

nieqiurong commented 1 year ago

5527 统一至此处讨论.