java指定字段映射名称_Java获取Mybatis中的映射字段名,根据实体类属性获取实际字段列名...

说明

项目如果需要动态的生成SQL语句,那么语句中的字段名是一个比较麻烦的事情,虽然Entity对象和数据表一般是一比一按照驼峰命名法和下划线命名法标准转换来映射的,但是简单的将Entity对象中的属性转为字段名是一个有风险的操作

有没有哪里记录了实体类属性和数据表字段的映射关系呢?那么你应该立即想到了mybatis mapper xml文件中的ResultMap了

如何获取mybatis的ResultMap?

原理过程

获取mybatis SqlSessionTemplate

获取回话配置

获取所有的ResultMap

根据会话配置获取指定id的ResultMap

读取ResultMap匹配到property属性和实体类属性名一致则返回

/**

* 获取实体类对应的mybatis mapper的resultMap映射对象

* 必须保证jdk1.8及以上

*

* @param clazz 实体类

* @return ResultMap

*/

private static ResultMap getBaseResultMap(Class> clazz) {

//获取SqlSessionTemplate

SqlSessionTemplate sqlSessionTemplate = ApplicationUtils.getBean(SqlSessionTemplate.class);

assert sqlSessionTemplate != null;

//关键在于这里,获取SqlSessionTemplate中的Configuration,这里面当前Sql seesion会话的所有参数

//Configuration的getResultMap方法就可以获取指定的ResultMap,所以是该方法需要指定ResultMap的ID

Configuration configuration = sqlSessionTemplate.getConfiguration();

//获取所有的ResultMap的名字:以xml的命名空间如:xx.xx.dao.StudentMapper加resultMap的id如:BaseResultMap组合:xx.xx.dao.StudentMapper.BaseResultMap这样的全定名

//注意会存在一个默认的BaseResultMap,为上面那个的短名称,所以我们会拿到项目所有的ResultMap

Collection resultMapNames = configuration.getResultMapNames();

//利用Stream流快速筛查

List resultMaps = resultMapNames.parallelStream()

.filter(name -> name.contains("."))//要全定名不要短名

.map(configuration::getResultMap)//根据全定名找到匹配的ResultMap

.filter(resultMap -> Objects.equals(resultMap.getType(), clazz))//匹配xml中type属性和实体类一致的

//排序,按字段数量来;这里还是会有多个,为什么:比如上面的xml中就有两个ResultMap

.sorted(Comparator.comparing(resultMap -> resultMap.getPropertyResultMappings().size()))

.collect(Collectors.toList());

//翻转,毕竟resultMap包含的字段多的属性映射更全嘛

Collections.reverse(resultMaps);

//找出那个type属性一致的,其实这个list里面所有的resultMap属性都是一致的了,毕竟上面过滤了,只不过Stream过滤就算只有一个也是那list装的

if (BeanUtils.isNotEmpty(resultMaps)) {

// return resultMaps.get(0);TODO 所以这里这样写和下面没毛病

for (ResultMap resultMap : resultMaps) {

Class> type = resultMap.getType();

if (Objects.equals(type, clazz)) {

return resultMap;

}

}

}

return null;

}

/**

* 根据实体类的属性名获取对应的数据表的字段列名

*

* @param property 属性名

* @param clazz 实体类

* @return 字段名

*/

public static String property2Field(String property, Class> clazz) {

ResultMap resultMap = getBaseResultMap(clazz);

if (BeanUtils.isNotEmpty(resultMap)) {

for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {

if (resultMapping.getProperty().equals(property)) {

property = resultMapping.getColumn();

return property;

}

}

}

//找不到resultMap就转下划线处理

String column = StringUtils.camelToUnderline(property, false);

log.warn("没有查询到Mapper中的ResultMap:" + property + "字段映射信息!将使用驼峰命名法转换下划线属性名:" + column);

return column;

}

当然,这样的方式是不能保证100%找到字段匹配的,如果resultMap没有配置是找不到的,那么就默认转下划线处理了。

转换方法

/**

* 驼峰转下划线

*

* @param param 字符串

* @param upperCase 是否全大写

* @return 结果

*/

public static String camelToUnderline(String param, boolean upperCase) {

if (param == null || "".equals(param.trim())) {

return "";

}

int len = param.length();

StringBuilder sb = new StringBuilder(len);

for (int i = 0; i < len; i++) {

char c = param.charAt(i);

if (Character.isUpperCase(c)) {

sb.append(UNDERLINE);

}

if (upperCase) {

//统一都转大写

sb.append(Character.toUpperCase(c));

} else {

//统一都转小写

sb.append(Character.toLowerCase(c));

}

}

return sb.toString();

}

Bean工具类代码

@Component

public class ApplicationUtils implements ApplicationContextAware {

private static ApplicationContext context;

public static T getBean(Class tClass) {

try {

return context.getBean(tClass);

} catch (Exception e) {

System.err.println("获取bean失败!");

}

return null;

}

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

context = applicationContext;

}

}

PS:注意以上操作还是有很大风险,如果保证ResultMap的正常配置和遵循命名法要求的话是没问题的。

关于Stream流操作不懂的可以参考博文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值