轉(zhuǎn)載:https://www.cnblogs.com/yql1986/p/9459478.html
通用Mapper是一款針對(duì)mybatis進(jìn)行擴(kuò)展的輕量級(jí)組件,使用起來(lái)非常方便蔬将。當(dāng)調(diào)用其針對(duì)mysql進(jìn)行批量添加數(shù)據(jù)的方法時(shí)谴仙,發(fā)現(xiàn)報(bào)錯(cuò),仔細(xì)研究了一番默伍,發(fā)現(xiàn)是在使用通用Mapper上出現(xiàn)了問(wèn)題欢嘿。下面貼出本文使用的通用的Mapper github 地址及其版本授霸。
通用Mapper github主頁(yè):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>{
}
批量添加數(shù)據(jù)的示例代碼:
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);
}
}
運(yùn)行程序后,出現(xiàn)如下錯(cuò)誤:
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
當(dāng)出現(xiàn)該錯(cuò)誤之后际插,隨手在網(wǎng)上搜索了一把碘耳,看看別人是怎么解決的。找到如下一篇文章(文章的鏈接如下文)框弛,非常遺憾該文章也沒(méi)有給出更加實(shí)際的解決辦法辛辨。
tk.mybatis.mapper.provider.SpecialProvider.<init>() 原文鏈接地址:https://www.cnblogs.com/softidea/p/6624766.html
我把目光停留在了用于訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的DAO層 TEntityDAO 類(lèi)上面蹂窖,該接口繼承了Mapper和MySqlMapper 兩個(gè)接口乾蛤,這兩個(gè)接口有啥區(qū)別呢? 帶著這個(gè)疑問(wèn)叶眉,我進(jìn)入到這兩個(gè)接口慷妙。細(xì)看了兩個(gè)接口之后僻焚,發(fā)現(xiàn)Mapper只是提供普通的CRUD,而批量添加數(shù)據(jù)接口在后者膝擂。兩者區(qū)別在這兒虑啤。下面貼出這兩個(gè)接口的截圖。
看到這兩個(gè)接口的區(qū)別架馋,回想到通用Mpper配置狞山,配置掃描時(shí)時(shí)只添加了通用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;
}
重新運(yùn)行程序后,還真是這兒的原因屏鳍。
總結(jié):通用Mapper基本的CRUD方法和批量操作數(shù)據(jù)庫(kù)的方法不是放在一起勘纯,需要由程序按需加載。
示例代碼已經(jīng)上傳到github钓瞭,代碼中沒(méi)有數(shù)據(jù)庫(kù)相關(guān)的配置驳遵,運(yùn)行代碼之前,需要把數(shù)據(jù)庫(kù)相關(guān)的配置補(bǔ)上降淮。
完整的代碼見(jiàn):https://github.com/gittorlight/springboot-example/tree/master/example3
以上是該博主解決springboot中整合mybatis的解決方法超埋,再springmvc中使用xml配置的,如下
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.sf.argus.web.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
再M(fèi)apperScannerConfigurer中有這樣的代碼
this.mapperHelper.ifEmptyRegisterDefaultInterface();
再點(diǎn)進(jìn)去是這樣的
/**
* 如果當(dāng)前注冊(cè)的接口為空佳鳖,自動(dòng)注冊(cè)默認(rèn)接口
*/
public void ifEmptyRegisterDefaultInterface() {
if (registerClass.size() == 0) {
registerMapper("tk.mybatis.mapper.common.Mapper");
}
}
確實(shí)只注冊(cè)了一個(gè)
所以霍殴,我們要自己指定注冊(cè)的mapper,改下xml加入屬性系吩,如下
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.sf.argus.web.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="properties">
<value>
mappers=tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.common.MySqlMapper
</value>
</property>
</bean>
再試試就ok了@赐ァ!穿挨!