• spring boot之使用通用Mapper批量添加数据


    通用Mapper是一款针对mybatis进行扩展的轻量级组件,使用起来非常方便。当调用其针对mysql进行批量添加数据的方法时,发现报错,仔细研究了一番,发现是在使用通用Mapper上出现了问题。下面贴出本文使用的通用的Mapper github 地址及其版本。

    通用Mapper github主页:https://github.com/abel533/Mapper/   本文示例使用的版本是3.5.4-SNAPSHOT 该分支的链接:  https://github.com/abel533/Mapper/tree/3.5.x


    继承通用Mapper的DAO层示例代码:

    package com.github.torlight.sbex;
    
    import tk.mybatis.mapper.common.Mapper;
    import tk.mybatis.mapper.common.MySqlMapper;
    
    public interface TEntityDAO extends Mapper<TEntityDO>,MySqlMapper<TEntityDO>{
        
    }

    批量添加数据的示例代码:

    package com.github.torlight.sbex;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ApplicationContext;
    
    @SpringBootApplication
    public class Example3Main {
    
        public static void main(String[] args) {
            
            ApplicationContext ctx=SpringApplication.run(Example3Main.class, args);
            
            System.out.println("Example3Main running...");
            
            List<TEntityDO> tEntityDOList=new ArrayList<TEntityDO>(10);
            tEntityDOList.add(new TEntityDO("1"));
            tEntityDOList.add(new TEntityDO("2"));
            tEntityDOList.add(new TEntityDO("3"));
            tEntityDOList.add(new TEntityDO("4"));
            tEntityDOList.add(new TEntityDO("5"));
            tEntityDOList.add(new TEntityDO("6"));
            tEntityDOList.add(new TEntityDO("7"));
            tEntityDOList.add(new TEntityDO("8"));
            tEntityDOList.add(new TEntityDO("9"));
            tEntityDOList.add(new TEntityDO("10"));
            
            TEntityDAO tEntityDAO=ctx.getBean(TEntityDAO.class);
            tEntityDAO.insertList(tEntityDOList);
                
        }
    
    }

    运行程序后,出现如下错误:

    Exception in thread "main" org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.SpecialProvider.dynamicSQL).  Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.SpecialProvider
        at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
        at com.sun.proxy.$Proxy62.insert(Unknown Source)
        at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:278)
        at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:57)
        at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
        at com.sun.proxy.$Proxy63.insertList(Unknown Source)
        at com.github.torlight.sbex.Example3Main.main(Example3Main.java:33)
    Caused by: org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.SpecialProvider.dynamicSQL).  Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.SpecialProvider
        at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:103)
        at org.apache.ibatis.builder.annotation.ProviderSqlSource.getBoundSql(ProviderSqlSource.java:73)
        at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:292)
        at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:64)
        at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:40)
        at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:46)
        at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:545)
        at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
        at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
        at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
        ... 6 more
    Caused by: java.lang.InstantiationException: tk.mybatis.mapper.provider.SpecialProvider
        at java.lang.Class.newInstance(Class.java:364)
        at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:85)
        ... 22 more

    当出现该错误之后,随手在网上搜索了一把,看看别人是怎么解决的。找到如下一篇文章(文章的链接如下文),非常遗憾该文章也没有给出更加实际的解决办法。

    tk.mybatis.mapper.provider.SpecialProvider.<init>()   原文链接地址:https://www.cnblogs.com/softidea/p/6624766.html


      我把目光停留在了用于访问数据库的DAO层 TEntityDAO 类上面,该接口继承了Mapper和MySqlMapper 两个接口,这两个接口有啥区别呢? 带着这个疑问,我进入到这两个接口。细看了两个接口之后,发现Mapper只是提供普通的CRUD,而批量添加数据接口在后者。两者区别在这儿。下面贴出这两个接口的截图。

                        通用Mapper接口

     

                      批量添加接口

     


     

    看到这两个接口的区别,回想到通用Mpper配置,配置扫描时时只添加了通用Mapper接口,tk.mybatis.mapper.common.Mapper ,是不是也要把批量添加的接口也要添加到接口扫描配置里面。

    通用接口扫描代码:

        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer(){
            
            Properties properties=new Properties();
            properties.put("mappers","tk.mybatis.mapper.common.Mapper");
    
            MapperScannerConfigurer msc=new MapperScannerConfigurer();      
            msc.getMapperHelper().setProperties(properties);
            msc.setBasePackage(DataSourceConfig.PACKAGE);
            msc.setSqlSessionFactoryBeanName(DataSourceConfig.SESSION_FACTORY_BEAN_NAME);
            
            return msc;
        }

    修改后的通用接口扫描代码:

        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer(){
            
            Properties properties=new Properties();
            properties.put("mappers","tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.common.MySqlMapper");
    
            MapperScannerConfigurer msc=new MapperScannerConfigurer();      
            msc.getMapperHelper().setProperties(properties);
            msc.setBasePackage(DataSourceConfig.PACKAGE);
            msc.setSqlSessionFactoryBeanName(DataSourceConfig.SESSION_FACTORY_BEAN_NAME);
            
            return msc;
        }

    重新运行程序后,还真是这儿的原因。

    总结:通用Mapper基本的CRUD方法和批量操作数据库的方法不是放在一起,需要由程序按需加载。

    示例代码已经上传到github,代码中没有数据库相关的配置,运行代码之前,需要把数据库相关的配置补上。

    完整的代码见:https://github.com/gittorlight/springboot-example/tree/master/example3

  • 相关阅读:
    Oracle中的exist和in
    oracle恢复误删数据
    【axios】API 说明
    Content-type对照表
    【gdal】创建GeoTiff栅格数据
    NPM使用
    【nodejs】request 和 response 对象
    【nodejs】express框架+mysql后台数据查询
    webapp网络定位
    JS对象创建的几种方法
  • 原文地址:https://www.cnblogs.com/yql1986/p/9459478.html
Copyright © 2020-2023  润新知