如何为@MybatisPlusTest的嵌入式H2数据库配置大小写忽略?
解决@MybatisPlusTest中H2数据库列名大小写敏感问题
问题背景
使用Spring + MyBatis Plus进行单元测试时,通过@MybatisPlusTest注解自动创建的嵌入式H2数据库,执行自定义查询后返回的Map结果集中,列名默认是大写(如NAME),无法通过小写的name获取值。相关信息如下:
数据库启动日志
2023-06-08 10:36:02.187 INFO 1911 --- [ main] beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version 2023-06-08 10:36:02.749 INFO 1911 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:e9cde56b-3395-44fb-8251-c79b0b36e653;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
表结构(schema-h2.sql)
create table if not exists person ( id int auto_increment primary key, name varchar(50) not null, age int not null );
Mapper代码
@Repository public interface PersonMapper extends BaseMapper<Person> { @Select("select name, age from person") public List<Map<String, Object>> selectCertainColumns(); }
可行解决方案
由于无法直接修改嵌入式H2的JDBC URL,可通过以下几种方式解决列名大小写问题:
1. 在SQL中指定小写列别名
修改Mapper的查询语句,用双引号包裹小写列名作为别名,强制H2返回小写的列名:
@Repository public interface PersonMapper extends BaseMapper<Person> { @Select("select name as \"name\", age as \"age\" from person") public List<Map<String, Object>> selectCertainColumns(); }
这样查询结果的Map中就会以小写的name、age作为key。
2. 配置MyBatis自动转换列名为小写
在测试环境的配置文件(如src/test/resources/application.properties)中添加MyBatis Plus配置:
# 开启下划线转驼峰规则(兼容下划线格式列名) mybatis-plus.configuration.map-underscore-to-camel-case=true # 使用列标签而非原始列名 mybatis-plus.configuration.use-column-label=true # 强制将结果列名转为小写 mybatis-plus.configuration.lower-case-column-names=true
添加后,MyBatis会自动将查询结果的列名转为小写,直接用rows.get(0).get("name")即可获取值。
3. 自定义BeanPostProcessor修改DataSource URL
通过Spring的BeanPostProcessor拦截自动创建的DataSource,在JDBC URL中添加CASE_INSENSITIVE_IDENTIFIERS=TRUE参数:
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.stereotype.Component; import javax.sql.DataSource; import java.lang.reflect.Field; @Component public class H2DataSourcePostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof DataSource) { DataSource dataSource = (DataSource) bean; try { // 反射获取原始URL Field urlField = dataSource.getClass().getDeclaredField("url"); urlField.setAccessible(true); String originalUrl = (String) urlField.get(dataSource); // 添加大小写不敏感参数 String newUrl = originalUrl + ";CASE_INSENSITIVE_IDENTIFIERS=TRUE"; // 重新构建DataSource return DataSourceBuilder.create() .url(newUrl) .username("sa") .password("") .driverClassName(dataSource.getClass().getName()) .build(); } catch (Exception e) { e.printStackTrace(); } } return bean; } }
将这个类放在测试类同包下,Spring启动时会自动拦截并修改DataSource,实现H2列名大小写不敏感。
4. 使用ResultMap映射列名
在Mapper中定义ResultMap,明确指定列名与Map key的对应关系:
@Repository public interface PersonMapper extends BaseMapper<Person> { @ResultMap("personMap") @Select("select name, age from person") public List<Map<String, Object>> selectCertainColumns(); @ResultMap(id = "personMap", value = { @Result(column = "NAME", property = "name"), @Result(column = "AGE", property = "age") }) void dummy(); // 仅用于定义ResultMap,无需实现 }
这样查询结果的Map会按照配置,将大写列名映射为小写key。
内容的提问来源于stack exchange,提问作者Hi computer
相关产品推荐
相关产品推荐

