求助一下:kotlin集成mybatis


#1

自定义mybatis插件时,用java开发一个简单的插件没有问题,但是把这个java代码自动转成kotlin时,启动服务,没有问题,同样访问就会报错。像是不兼容。求大神给个能用kotlin解决的办法。由于我没权限,访客只能贴一张图,所以只能把错误贴了一下。

  1. java写的mybatis插件(为了验证,打印 插件拦截方法......字样)
    // 定义拦截签名
    @Intercepts({
    @Signature(type = StatementHandler.class, method = “prepare”, args = { Connection.class, Integer.class }) })
    public class MyPlugin implements Interceptor {

     Properties properties = null;
    
     // 拦截方法逻辑
     @Override
     public Object intercept(Invocation invocation) throws Throwable {
     	System.out.println("插件拦截方法......");
     	return invocation.proceed();
     }
    
     // 生成MyBatis拦截器代理对象
     @Override
     public Object plugin(Object target) {
     	return Plugin.wrap(target, this);
     }
    
     // 设置插件属性
     @Override
     public void setProperties(Properties properties) {
     	this.properties = properties;
     }
    

    }

  2. 查询数据库,mybatis持久
    http://localhost:8888/mybatis/getUser?id=1
    查询结果返回
    |id|1|
    |—|---|
    |userName|“Eic”|
    |sex|“MALE”|
    |note|“update insert data”|

  3. mybatis插件生效 有输出日志为证(如预期打印了 插件拦截方法......字样)
    2019-05-18 21:49:59.248 DEBUG 2034 — [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet : enableLoggingRequestDetails=‘false’: request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
    2019-05-18 21:49:59.248 INFO 2034 — [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 43 ms
    2019-05-18 21:49:59.286 DEBUG 2034 — [nio-8888-exec-1] org.apache.tomcat.util.http.Parameters : Set encoding to UTF-8
    2019-05-18 21:49:59.286 DEBUG 2034 — [nio-8888-exec-1] org.apache.tomcat.util.http.Parameters : Decoding query null UTF-8
    2019-05-18 21:49:59.287 DEBUG 2034 — [nio-8888-exec-1] org.apache.tomcat.util.http.Parameters : Start processing with input [id=1]
    2019-05-18 21:49:59.287 DEBUG 2034 — [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet : GET “/mybatis/getUser?id=1”, parameters={masked}
    2019-05-18 21:49:59.418 DEBUG 2034 — [nio-8888-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public com.vv.custom.demovsgk.pojo.User com.vv.custom.demovsgk.controller.MyBatisController.getUser(long)
    2019-05-18 21:49:59.426 DEBUG 2034 — [nio-8888-exec-1] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
    2019-05-18 21:49:59.555 DEBUG 2034 — [nio-8888-exec-1] org.mybatis.spring.SqlSessionUtils : Creating a new SqlSession
    2019-05-18 21:49:59.571 DEBUG 2034 — [nio-8888-exec-1] org.mybatis.spring.SqlSessionUtils : SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e03f9b7] was not registered for synchronization because synchronization is not active
    2019-05-18 21:49:59.583 DEBUG 2034 — [nio-8888-exec-1] o.s.jdbc.datasource.DataSourceUtils : Fetching JDBC Connection from DataSource
    2019-05-18 21:49:59.585 DEBUG 2034 — [nio-8888-exec-1] o.m.s.t.SpringManagedTransaction : JDBC Connection [1733754557, URL=jdbc:h2:/Users/baronwei/DevDirectory/product/testDB/springLearning/spring_boot_app_db, UserName=SA, H2 JDBC Driver] will not be managed by Spring
    插件拦截方法…
    2019-05-18 21:49:59.592 DEBUG 2034 — [nio-8888-exec-1] c.v.c.d.dao.MyBatisUserDao.getUser : ==> Preparing: select id, user_name as userName, sex, note from t_user where id = ?
    2019-05-18 21:49:59.639 DEBUG 2034 — [nio-8888-exec-1] c.v.c.d.dao.MyBatisUserDao.getUser : ==> Parameters: 1(Long)
    2019-05-18 21:49:59.715 DEBUG 2034 — [nio-8888-exec-1] c.v.c.d.dao.MyBatisUserDao.getUser : <== Total: 1
    2019-05-18 21:49:59.720 DEBUG 2034 — [nio-8888-exec-1] org.mybatis.spring.SqlSessionUtils : Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e03f9b7]
    2019-05-18 21:49:59.833 DEBUG 2034 — [nio-8888-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Using ‘application/json;q=0.8’, given [text/html, application/xhtml+xml, application/xml;q=0.9, /;q=0.8] and supported [application/json, application/+json, application/json, application/+json]
    2019-05-18 21:49:59.834 DEBUG 2034 — [nio-8888-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Writing [User(id=1, userName=Eic, sex=MALE, note=update insert data)]
    2019-05-18 21:49:59.875 DEBUG 2034 — [nio-8888-exec-1] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
    2019-05-18 21:49:59.875 DEBUG 2034 — [nio-8888-exec-1] o.s.web.servlet.DispatcherServlet : Completed 200 OK
    2019-05-18 21:49:59.879 DEBUG 2034 — [nio-8888-exec-1] o.a.tomcat.util.net.SocketWrapperBase : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@ebdcdaa:org.apache.tomcat.util.net.NioChannel@88cf652:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8888 remote=/0:0:0:0:0:0:0:1:50806]], Read from buffer: [0]
    2019-05-18 21:49:59.879 DEBUG 2034 — [nio-8888-exec-1] org.apache.tomcat.util.net.NioEndpoint : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@ebdcdaa:org.apache.tomcat.util.net.NioChannel@88cf652:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8888 remote=/0:0:0:0:0:0:0:1:50806]], Read direct from socket: [0]
    2019-05-18 21:49:59.880 DEBUG 2034 — [nio-8888-exec-1] o.apache.coyote.http11.Http11Processor : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@ebdcdaa:org.apache.tomcat.util.net.NioChannel@88cf652:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8888 remote=/0:0:0:0:0:0:0:1:50806]], Status in: [OPEN_READ], State out: [OPEN]
    2019-05-18 21:50:43.862 DEBUG 2034 — [alina-utility-2] org.apache.catalina.session.ManagerBase : Start expire sessions StandardManager at 1558187443861 sessioncount 0
    2019-05-18 21:50:43.862 DEBUG 2034 — [alina-utility-2] org.apache.catalina.session.ManagerBase : End expire sessions StandardManager processingTime 1 expired sessions: 0

  4. java写的mybatis插件,转成kotlin版,没有编译错误
    // 定义拦截签名
    @Intercepts(Signature(type = StatementHandler::class, method = “prepare”, args = [Connection::class, Int::class]))
    class MyPlugin : Interceptor {

     var properties2: Properties? = null
    
     // 拦截方法逻辑
     @Throws(Throwable::class)
     override fun intercept(invocation: Invocation): Any {
         println("插件拦截方法......")
         return invocation.proceed()
     }
    
     // 生成MyBatis拦截器代理对象
     override fun plugin(target: Any): Any {
         return Plugin.wrap(target, this)
     }
    
     // 设置插件属性
     override fun setProperties(properties: Properties) {
         this.properties2 = properties
     }
    

    }

  5. 重启服务,无错误

  6. 再次同样访问


    Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat May 18 21:13:23 CST 2019
There was an unexpected error (type=Internal Server Error, status=500).

Error opening session. Cause: org.apache.ibatis.plugin.PluginException: Could not find method on interface org.apache.ibatis.executor.statement.StatementHandler named prepare. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.executor.statement.StatementHandler.prepare(java.sql.Connection, int) ### Cause: org.apache.ibatis.plugin.PluginException: Could not find method on interface org.apache.ibatis.executor.statement.StatementHandler named prepare. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.executor.statement.StatementHandler.prepare(java.sql.Connection, int)

org.apache.ibatis.exceptions.PersistenceException:

Error opening session. Cause: org.apache.ibatis.plugin.PluginException: Could not find method on interface org.apache.ibatis.executor.statement.StatementHandler named prepare. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.executor.statement.StatementHandler.prepare(java.sql.Connection, int)

Cause: org.apache.ibatis.plugin.PluginException: Could not find method on interface org.apache.ibatis.executor.statement.StatementHandler named prepare. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.executor.statement.StatementHandler.prepare(java.sql.Connection, int)

at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:100)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSession(DefaultSqlSessionFactory.java:57)
at org.mybatis.spring.SqlSessionUtils.getSqlSession(SqlSessionUtils.java:98)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:428)
at com.sun.proxy.$Proxy116.selectOne(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:166)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58)
at com.sun.proxy.$Proxy117.getUser(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy118.getUser(Unknown Source)
at com.vv.custom.demovsgk.service.impl.MyBatisUserServiceImpl.getUser(MyBatisUserServiceImpl.kt:17)
at com.vv.custom.demovsgk.controller.MyBatisController.getUser(MyBatisController.kt:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.ibatis.plugin.PluginException: Could not find method on interface org.apache.ibatis.executor.statement.StatementHandler named prepare. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.executor.statement.StatementHandler.prepare(java.sql.Connection, int)
at org.apache.ibatis.plugin.Plugin.getSignatureMap(Plugin.java:83)
at org.apache.ibatis.plugin.Plugin.wrap(Plugin.java:44)
at com.vv.custom.demovsgk.plugin.MyPlugin.plugin(MyPlugin.kt:29)
at org.apache.ibatis.plugin.InterceptorChain.pluginAll(InterceptorChain.java:31)
at org.apache.ibatis.session.Configuration.newExecutor(Configuration.java:599)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:96)
… 75 more
Caused by: java.lang.NoSuchMethodException: org.apache.ibatis.executor.statement.StatementHandler.prepare(java.sql.Connection, int)
at java.lang.Class.getMethod(Class.java:1786)
at org.apache.ibatis.plugin.Plugin.getSignatureMap(Plugin.java:80)
… 80 more


#2

@Intercepts(Signature(type = StatementHandler::class, method = “prepare”, args = [Connection::class, Int::class]))

这一行有问题,Int::class 改成 java.lang.Integer::class


#3

因为你要拦截的方法的参数类型是 Integer,但是 Kotlin 里面直接写 Int::class 在这种情况下会映射为 Java 中的 int.class


#4

感谢大神的回答,改完之后,确实可以了。

我又查阅了一下,我学习的书籍误导了我,说kotlin的Int类型是可以使用方法的,所以它对应java的Integer包装类,现在看应该说的是使用时。但是没有说编译后的情况。按您说的,Int:class在这种情况下会被映射为Java的int.class,在这个指引下,我又查阅了kotlin的其他书籍,有描述:大多会被编译成int.class,但泛型时会被编译成Integer.class。那是不是,kotlin应该把在注解中的Int::class也应该直接编译成Integer.class会不会就方便多了呢


#5

我觉得这样设计没毛病

现在默认编译成 int.class,你遇到问题的时候还可以改成 java.lang.Integer::class 避开。

如果默认编译成 Integer.class,而你又遇到另一个问题,需要 int.class,那要怎么办呢?


#6

注解里的Int::class,大多都想要被编译成Integer.class吧
另外,在kotlin的代码中,是不是本着尽量少引用java的类型,多用kotlin的类型呢?
再者,以后如果有机会脱离jvm的话,是不是咱们写的代码,就更少的不需要修改呢?


#7


京ICP备16022265号-2 Kotlin China 2017 - 2018
本站由腾讯云提供计算服务