Spring与MyBatis集成测试报错:java.lang.IllegalAccessError求助
我之前也踩过这个坑,折腾了好一阵才摸清楚问题根源,给你梳理下:
问题场景
你在做Spring与MyBatis的集成,用JDK 1.8运行这段测试代码时触发了错误:
@Test public void testFindUserById() throws Exception{ UserMapper userMapper=(UserMapper)applicationContext.getBean("userMapper"); User user=userMapper.findUserById(1); System.out.println(user); }
错误堆栈信息为:
java.lang.IllegalAccessError: org.apache.commons.dbcp.DelegatingPreparedStatement.isClosed()Z
你的Spring数据源配置使用的是org.apache.commons.dbcp.BasicDataSource。
错误原因
这个问题的核心是Commons DBCP版本与JDBC 4.0规范不兼容:
JDBC 4.0(对应JDK 1.6及以上)要求PreparedStatement的isClosed()方法必须是public修饰,但旧版本的Commons DBCP(比如1.3及更早)中,DelegatingPreparedStatement的isClosed()方法是包级访问权限(无public修饰)。当Spring或MyBatis尝试调用这个方法时,就会因权限不足抛出IllegalAccessError。
解决方案
给你几个优先级从高到低的解决办法:
升级Commons DBCP到兼容版本:直接把DBCP版本升到1.4及以上(若用DBCP1),更推荐换成现在的主流版本DBCP2。比如Maven依赖可以改成:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.9.0</version> </dependency>注意用DBCP2的话,数据源类要换成
org.apache.commons.dbcp2.BasicDataSource,配置参数和旧版本基本一致,不用大改。清理依赖树,排除冲突版本:如果项目里是间接引入了旧版本DBCP(比如通过其他依赖带进来),要在Maven/Gradle里排除低版本依赖。比如Maven中可以这么做:
<dependency> <!-- 这里是引入旧DBCP的依赖 --> <groupId>xxx</groupId> <artifactId>xxx</artifactId> <exclusions> <exclusion> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> </exclusion> </exclusions> </dependency>更换数据源实现:如果暂时不想升级DBCP,可以换成其他数据源,比如性能更优的HikariCP(现在Spring Boot默认使用),或者Spring自带的
org.springframework.jdbc.datasource.SimpleDriverDataSource——不过后者是简单实现,不适合生产环境。
内容的提问来源于stack exchange,提问作者Peter

