MyBatis-Plus分页插件使用避坑:cannot be cast to com.baomidou.mybatisplus.core.metadata.IPage
1.bug背景
1.1.Spring配置文件
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--连接池中保持最大的连接数-->
<property name="maxActive" value="10"/>
<!--连接池初始化的时候创建几个-->
<property name="initialSize" value="5"/>
</bean>
<!--把MyBatis交给Sring容器管理-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--引入MyBatis的配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--注册映射文件-->
<property name="mapperLocations">
<array>
<value>classpath:mappers/*.xml</value>
</array>
</property>
</bean>
<!--扫描MyBatis需要动态代理的接口所在的包-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="pers.lintao.dao"/>
</bean>
1.2.MyBatis配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--下划线转驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<plugins>
<!--配置MyBatis-plus分页插件拦截器-->
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor">
<property name="overflow" value="true"/>
<property name="dbType" value="MYSQL"/>
</plugin>
</plugins>
</configuration>
1.3.dao层方法
/**
* mybatis-plus分页查询
* @param page
* @param queryWrapper
* @return
*/
IPage<DepartmentListResponseDTO> queryPageList(Page<DepartmentListRequestDTO> page, @Param("ew") Wrapper<DepartmentListRequestDTO> queryWrapper);
1.4.mapper映射文件
<select id="queryPageList" resultType="pers.lintao.dto.responseDTO.DepartmentListResponseDTO">
SELECT dep_id,name,address,status
FROM department ${ew.customSqlSegment}
</select>
1.5.相关实体
DepartmentListRequestDTO和DepartmentListResponseDTO都存在
1.6.Junit测试单元
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@WebAppConfiguration
public class DepartmentDaoTest {
@Autowired
private DepartmentDao departmentDao;
@Test
public void queryPageList() {
QueryWrapper<DepartmentListRequestDTO> wrapper = new QueryWrapper<>();
wrapper.like("name", "学习");
wrapper.eq("status",1);
Page<DepartmentListRequestDTO> page = new Page<>(1, 10);
IPage<DepartmentListResponseDTO> iPage = departmentDao.queryPageList(page, wrapper);
System.out.println(iPage);
}
}
2.Bug详情
08:52:54.536 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@61ecbee9] will not be managed by Spring
08:52:54.550 [main] DEBUG com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize - JsqlParserCountOptimize sql=SELECT dep_id,name,address,status
FROM department WHERE (name LIKE ? AND status = ?)
08:52:54.587 [main] DEBUG pers.lintao.dao.DepartmentDao.queryPageList - ==> Preparing: SELECT COUNT(1) FROM department WHERE (name LIKE ? AND status = ?)
08:52:54.613 [main] DEBUG pers.lintao.dao.DepartmentDao.queryPageList - ==> Parameters: %学习%(String), 1(Integer)
08:52:54.673 [main] DEBUG pers.lintao.dao.DepartmentDao.queryPageList - ==> Preparing: SELECT dep_id,name,address,status FROM department WHERE (name LIKE ? AND status = ?) LIMIT ?,?
08:52:54.674 [main] DEBUG pers.lintao.dao.DepartmentDao.queryPageList - ==> Parameters: %学习%(String), 1(Integer), 0(Long), 10(Long)
08:52:54.681 [main] DEBUG pers.lintao.dao.DepartmentDao.queryPageList - <== Total: 1
08:52:54.682 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@767191b1]
08:52:54.683 [main] DEBUG org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate - Retrieved ApplicationContext [385337537] from cache with key [[WebMergedContextConfiguration@6950e31 testClass = DepartmentDaoTest, locations = '{classpath:applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]]
08:52:54.683 [main] DEBUG org.springframework.test.context.cache - Spring test ApplicationContext cache statistics: [DefaultContextCache@18da4dd size = 1, maxSize = 32, parentContextCount = 0, hitCount = 5, missCount = 1]
08:52:54.685 [main] DEBUG org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate - Retrieved ApplicationContext [385337537] from cache with key [[WebMergedContextConfiguration@6950e31 testClass = DepartmentDaoTest, locations = '{classpath:applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]]
08:52:54.685 [main] DEBUG org.springframework.test.context.cache - Spring test ApplicationContext cache statistics: [DefaultContextCache@18da4dd size = 1, maxSize = 32, parentContextCount = 0, hitCount = 6, missCount = 1]
08:52:54.685 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - After test method: context [DefaultTestContext@2db7a79b testClass = DepartmentDaoTest, testInstance = pers.lintao.dao.DepartmentDaoTest@4195105b, testMethod = queryPageList@DepartmentDaoTest, testException = java.lang.ClassCastException: pers.lintao.dto.responseDTO.DepartmentListResponseDTO cannot be cast to com.baomidou.mybatisplus.core.metadata.IPage, mergedContextConfiguration = [WebMergedContextConfiguration@6950e31 testClass = DepartmentDaoTest, locations = '{classpath:applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].
08:52:54.685 [main] DEBUG org.springframework.test.context.web.ServletTestExecutionListener - Resetting RequestContextHolder for test context [DefaultTestContext@2db7a79b testClass = DepartmentDaoTest, testInstance = pers.lintao.dao.DepartmentDaoTest@4195105b, testMethod = queryPageList@DepartmentDaoTest, testException = java.lang.ClassCastException: pers.lintao.dto.responseDTO.DepartmentListResponseDTO cannot be cast to com.baomidou.mybatisplus.core.metadata.IPage, mergedContextConfiguration = [WebMergedContextConfiguration@6950e31 testClass = DepartmentDaoTest, locations = '{classpath:applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]].
java.lang.ClassCastException: pers.lintao.dto.responseDTO.DepartmentListResponseDTO cannot be cast to com.baomidou.mybatisplus.core.metadata.IPage
at com.sun.proxy.$Proxy41.queryPageList(Unknown Source)
at pers.lintao.dao.DepartmentDaoTest.queryPageList(DepartmentDaoTest.java:34)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
3.分析Bug的可能
3.1.可能一:Page对象的位置
<!--MyBatis-Plus官方文档明确说明:使用他的分页插件是Page对象在声明方法是必须位于第一个参数的位置-->
IPage<DepartmentListResponseDTO> queryPageList(Page<DepartmentListRequestDTO> page, @Param("ew") Wrapper<DepartmentListRequestDTO> queryWrapper);
IPage<DepartmentListResponseDTO> iPage = departmentDao.queryPageList(page, wrapper);
3.2.可能二:MyBatis-Plus分页插件配置有问题
MyBatis配置文件中<configuration>的子元素的配置有严格的顺序要求,结合spring配置的话,可能也需要注意他的先后顺序:The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".
4.解决Bug
可能一不成立,我的方法声明和使用Page对象都是在首位
可能二不成立,在Mybatis配置文件中子元素顺序不对会直接报错;而配合Spring配置文件配置时不需要考虑属性的先后顺序
出错位置:在Spring配置文件中配置SqlSessionFactory时,使用的是mybatis-spring包中的,应该使用MyBatis-Plus中的,因为在引入MyBatis-Plus时,它会顺带引入mybatis和mybatis-spring的依赖;为了避免jar冲突我们一般就不自己引入mybatis和mybatis-spring的依赖
<!-- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--注册映射文件-->
<property name="mapperLocations">
<array>
<value>classpath:mappers/*.xml</value>
</array>
</property>
<!--引入MyBatis的配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
版权声明:程序员胖胖胖虎阿 发表于 2022年9月15日 下午1:00。
转载请注明:MyBatis-Plus分页插件使用避坑:cannot be cast to com.baomidou.mybatisplus.core.metadata.IPage | 胖虎的工具箱-编程导航
转载请注明:MyBatis-Plus分页插件使用避坑:cannot be cast to com.baomidou.mybatisplus.core.metadata.IPage | 胖虎的工具箱-编程导航
相关文章
暂无评论...