安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

MyBatisPlus中如何使用ResultMap

10月26日 月依兮投稿
  作者:字节飞扬
  原文链接:https:www。cnblogs。combytesflypresultmapinmybatisplus。html
  MyBatisPlus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。
  MyBatisPlus对MyBatis基本零侵入,完全可以与MyBatis混合使用,这点很赞。
  在涉及到关系型数据库增删查改的业务时,我比较喜欢用MyBatisPlus,开发效率极高。具体的使用可以参考官网,或者自己上手摸索感受一下。
  下面简单总结一下在MyBatisPlus中如何使用ResultMap。问题说明
  先看个例子:
  有如下两张表:createtabletbbook(idbigintprimarykey,namevarchar(32),authorvarchar(20));createtabletbhero(idbigintprimarykey,namevarchar(32),ageint,skillvarchar(32),bidbigint);
  其中,tbhero中的bid关联tbbook表的id。
  下面先看Hero实体类的代码,如下:importcom。baomidou。mybatisplus。annotation。TableFimportcom。baomidou。mybatisplus。annotation。TableId;importcom。baomidou。mybatisplus。annotation。TableNimportcom。fasterxml。jackson。annotation。JsonIimportlombok。Gimportlombok。NoArgsCimportlombok。SGetterSetterNoArgsConstructorTableName(tbhero)JsonInclude(JsonInclude。Include。NONNULL)publicclassHero{TableId(id)privateLTableField(valuename,keepGlobalFormattrue)privateSTableField(valueage,keepGlobalFormattrue)privateITableField(valueskill,keepGlobalFormattrue)privateSTableField(valuebid,keepGlobalFormattrue)privateLongbookId;数据库表中不存在以下字段(表join时会用到)TableField(valuebookname,existfalse)privateStringbookNTableField(valueauthor,existfalse)privateS}
  注意了,我特地把tbhero表中的bid字段映射成实体类Hero中的bookId属性。测试BaseMapper中内置的insert()方法或者IService中的save()方法
  MyBatisPlus打印出的SQL为:Preparing:INSERTINTOtbhero(id,name,age,skill,bid)VALUES(?,?,?,?,?)Parameters:1589788935356416(Long),阿飞(String),18(Integer),天下第一快剑(String),1(Long)
  没毛病,MyBatisPlus会根据TableField指定的映射关系,生成对应的SQL。测试BaseMapper中内置的selectById()方法或者IService中的getById()方法
  MyBatisPlus打印出的SQL为:Preparing:SELECTid,name,age,skill,bidASbookIdFROMtbheroWHEREid?Parameters:1(Long)
  也没毛病,可以看到生成的SELECT中把bid做了别名bookId。测试自己写的SQL
  比如现在我想连接tbhero与tbbook这两张表,如下:MapperRepositorypublicinterfaceHeroMapperextendsBaseMapperHero{Select({SELECTtbhero。,tbbook。nameasbookname,tbbook。authorFROMtbheroLEFTJOINtbbookONtbhero。bidtbbook。id{ew。customSqlSegment}})IPageHeropageQueryHero(Param(Constants。WRAPPER)WrapperHeroqueryWrapper,PageHeropage);}
  查询MyBatisPlus打印出的SQL为:Preparing:SELECTtbhero。,tbbook。nameASbookname,tbbook。authorFROMtbheroLEFTJOINtbbookONtbhero。bidtbbook。idWHERE(bid?)ORDERBYidASCLIMIT?OFFSET?Parameters:2(Long),1(Long),1(Long)
  SQL没啥问题,过滤与分页也都正常,但是此时你会发现bookId属性为null,如下:
  为什么呢?
  调用BaseMapper中内置的selectById()方法并没有出现这种情况啊???
  回过头来再对比一下在HeroMapper中自己定义的查询与MyBatisPlus自带的selectById()有啥不同,还记得上面的刚刚的测试吗,生成的SQL有啥不同?
  原来,MyBatisPlus为BaseMapper中内置的方法生成SQL时,会把SELECT子句中bid做别名bookId,而自己写的查询MyBatisPlus并不会帮你修改SELECT子句,也就导致bookId属性为null。解决方法方案一:表中的字段与实体类的属性严格保持一致(字段有下划线则属性用驼峰表示)
  在这里就是tbhero表中的bid字段映射成实体类Hero中的bid属性。这样当然可以解决问题,但不是本篇讲的重点。方案二:把自己写的SQL中bid做别名bookId方案三:使用ResultMap,这是此篇的重点
  在TableName设置autoResultMaptrueTableName(valuetbhero,autoResultMaptrue)publicclassHero{}
  然后在自定义查询中添加ResultMap注解,如下:importorg。apache。ibatis。annotations。Mimportorg。apache。ibatis。annotations。Pimportorg。apache。ibatis。annotations。ResultMimportorg。apache。ibatis。annotations。Simportorg。springframework。stereotype。RMapperRepositorypublicinterfaceHeroMapperextendsBaseMapperHero{ResultMap(mybatisplusHero)Select({SELECTtbhero。,tbbook。nameasbookname,tbbook。authorFROMtbheroLEFTJOINtbbookONtbhero。bidtbbook。id{ew。customSqlSegment}})IPageHeropageQueryHero(Param(Constants。WRAPPER)WrapperHeroqueryWrapper,PageHeropage);}
  这样,也能解决问题。
  下面简单看下源码,ResultMap(mybatisplus实体类名)怎么来的。
  详情见:com。baomidou。mybatisplus。core。metadata。TableInfoinitResultMapIfNeed()自动构建resultMap并注入(如果条件符合的话)voidinitResultMapIfNeed(){if(autoInitResultMapnullresultMap){StringidcurrentNamespaceDOTMYBATISPLUSUNDERSCOREentityType。getSimpleName();ListResultMappingresultMappingsnewArrayList();if(havePK()){ResultMappingidMappingnewResultMapping。Builder(configuration,keyProperty,StringUtils。getTargetColumn(keyColumn),keyType)。flags(Collections。singletonList(ResultFlag。ID))。build();resultMappings。add(idMapping);}if(CollectionUtils。isNotEmpty(fieldList)){fieldList。forEach(iresultMappings。add(i。getResultMapping(configuration)));}ResultMapresultMapnewResultMap。Builder(configuration,id,entityType,resultMappings)。build();configuration。addResultMap(resultMap);this。resultM}}
  注意看上面的字符串id的构成,你应该可以明白。
  思考:这种方式的ResultMap默认是强绑在一个TableName上的,如果是某个聚合查询或者查询的结果并非对应一个真实的表怎么办呢?有没有更优雅的方式?自定义AutoResultMap注解
  基于上面的思考,我做了下面简单的实现:自定义AutoResultMap注解importjava。lang。annotation。;使用AutoResultMap注解的实体类自动生成{auto。mybatisplus类名}为id的resultMap{linkMybatisPlusConfiginitAutoResultMap()}DocumentedRetention(RetentionPolicy。RUNTIME)Target(ElementType。TYPE)publicinterfaceAutoResultMap{}启动时扫描AutoResultMap注解的实体类packagecom。bytesfly。mybatis。importcn。hutool。core。util。ClassUimportcn。hutool。core。util。ReflectUimportcom。baomidou。mybatisplus。annotation。DbTimportcom。baomidou。mybatisplus。core。metadata。TableIimportcom。baomidou。mybatisplus。core。metadata。TableInfoHimportcom。baomidou。mybatisplus。extension。plugins。MybatisPlusIimportcom。baomidou。mybatisplus。extension。plugins。inner。PaginationInnerIimportcom。baomidou。mybatisplus。extension。toolkit。JdbcUimportcom。bytesfly。mybatis。annotation。AutoResultMimportlombok。extern。slf4j。Slf4j;importorg。apache。ibatis。builder。MapperBuilderAimportorg。mybatis。spring。SqlSessionTimportorg。mybatis。spring。annotation。MapperSimportorg。springframework。beans。factory。annotation。Aimportorg。springframework。boot。autoconfigure。jdbc。DataSourcePimportorg。springframework。context。annotation。Bimportorg。springframework。context。annotation。Cimportorg。springframework。transaction。annotation。EnableTransactionMimportjavax。annotation。PostCimportjava。util。S可添加一些插件ConfigurationEnableTransactionManagement(proxyTargetClasstrue)MapperScan(basePackagescom。bytesfly。mybatis。mapper)Slf4jpublicclassMybatisPlusConfig{AutowiredprivateSqlSessionTemplatesqlSessionT分页插件(根据jdbcUrl识别出数据库类型,自动选择适合该方言的分页插件)相关使用说明:https:baomidou。comguidepage。htmlBeanpublicMybatisPlusInterceptormybatisPlusInterceptor(DataSourcePropertiesdataSourceProperties){StringjdbcUrldataSourceProperties。getUrl();DbTypedbTypeJdbcUtils。getDbType(jdbcUrl);MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();interceptor。addInnerInterceptor(newPaginationInnerInterceptor(dbType));}AutoResultMap注解的实体类自动构建resultMap并注入PostConstructpublicvoidinitAutoResultMap(){try{log。info(startregisterAutoResultMap);SStringpackageNamecom。bytesfly。mybatis。model。db。SetC?classesClassUtil。scanPackageByAnnotation(packageName,AutoResultMap。class);org。apache。ibatis。session。ConfigurationconfigurationsqlSessionTemplate。getConfiguration();for(Classclazz:classes){MapperBuilderAssistantassistantnewMapperBuilderAssistant(configuration,);assistant。setCurrentNamespace(namespace);TableInfotableInfoTableInfoHelper。initTableInfo(assistant,clazz);if(!tableInfo。isAutoInitResultMap()){设置tableInfo的autoInitResultMap属性为trueReflectUtil。setFieldValue(tableInfo,autoInitResultMap,true);调用tableInfoinitResultMapIfNeed()方法,自动构建resultMap并注入ReflectUtil。invoke(tableInfo,initResultMapIfNeed);}}log。info(finishregisterAutoResultMap);}catch(Throwablee){log。error(initAutoResultMaperror,e);System。exit(1);}}}
  关键代码其实没有几行,耐心看下应该不难懂。使用AutoResultMap注解
  还是用例子来说明更直观。
  下面是一个聚合查询:MapperRepositorypublicinterfaceBookMapperextendsBaseMapperBook{ResultMap(auto。mybatisplusBookAgg)Select({SELECTtbbook。id,max(tbbook。name)asname,arrayagg(distincttbhero。idorderbytbhero。idasc)asheroidsFROMtbheroINNERJOINtbbookONtbhero。bidtbbook。idGROUPBYtbbook。id})ListBookAggagg();}
  其中BookAgg的定义如下,在实体类上使用了AutoResultMap注解:GetterSetterNoArgsConstructorAutoResultMappublicclassBookAgg{TableId(id)privateLongbookId;TableField(name)privateStringbookNTableField(heroids)privateObjectheroI}
投诉 评论 转载

国泰君安证券积极关注互联网估值修复,推荐腾讯快手哔哩哔哩阅文【传媒】行业政策底夯实,估值性价比凸显事件:2022年5月17日全国政协召开数字经济专题协商会,政协主席汪洋提出不断做强做优做大数字经济,使之更好服务和融入新发展格局、推……2022年春节最值得买的几款手机,价格不高性能强悍,直接买就新年到,不知道朋友们有没有考虑更换手机的朋友,如果没有做好决定不妨看看妖妖推荐的这几款手机,绝对是目前最值得买的几款手机,个个性能强悍,最关键的是价格不高,想要购机的小伙伴可以……罗永浩出手!五分钟卖5万件剃须刀,小米当年我还卖到破纪录呢一把好用的剃须刀对于广大男士来说就如同女人的口红一样重要大多数男生的胡子长得特别快一天不刮都不行每年365天天都要刮胡子如果一天不刮胡茬就长出来了显得十分的邋遢、不……京东和阿里巴巴又撕破脸了?今天一打开热搜,我就被这个榜单震惊了!阿里涉嫌侵犯女同事男员工被辞退和阿里公布处理决定的热搜下面,竟然紧紧跟了一条京东的广告??就挺魔幻的而且你敢信,这种操作……腾讯为什么强力推荐QQ用户转Tim?不止题主这样问,很多人都不解为什么腾讯极力提倡大家升级到TIM。TIM可以说是一款办公为主的软件,是腾讯主打的在企业社交方面的产品。其实界面只不过比QQ要简洁化而已……MyBatisPlus中如何使用ResultMap作者:字节飞扬原文链接:https:www。cnblogs。combytesflypresultmapinmybatisplus。htmlMyBatisPlus(简……为什么普遍生活水平都提高了,有些人还是要抱怨?在面对这种问题时,有些人生活水平提高了,还有些这人生活水平下降,所以说也会招来个别人的反感轻蔑和嫉妒。不只是生活水平提高的问题,更重要的是渴望社会公平,公正,平等,诚信,和谐,……买手机不能贪便宜买手机真不能贪便宜,因为不是使用一两天的事情,看似赚了其实吃大亏,日后长时间使用会一直后悔,必须得旗舰机。次旗舰机和性价比手机不止减配,品控还不行。以前买过几部旗舰机用了四五年……心系中原,力挺河南,广汽三菱提高置换补贴近期,备受全国关注的720河南暴雨,终于迎来了暴雨过后的大晴天。这座城市正在渐渐恢复,一个明显的迹象是马路上随处可见、像搁浅的鲸鱼一样的车辆越来越少风雨终会过去,关爱从不……北京多部门约谈马蜂窝要求立即整改中关村在线消息:北京市通信管理局最近发文称,会同市文化和旅游局、市网信办对北京蚂蜂窝网络科技有限公司进行了约谈,要求立即进行整改。马蜂窝官网据了解,此次约谈蚂蜂窝旅……传说中的MIUI精简版,从小米音乐开始?从MIUI12。5正式推送之前,就有不少数码爱好者甚至知名博主猜测,MIUI13主打的方向将会是精简冗余代码、提升稳定性和流畅度,甚至还将大幅减少广告。呐,如果这是真的,……现在小偷比以前少了,是因为祖国富强了吗?富与穷于小偷多少没有绝对的关系,法律意识才是起关键的,决定性的作用〔大笑〕〔大笑〕〔大笑〕〔祈祷〕一是时代发展,生活改善。二是科技发展,摄像天眼。三是治安稳定……
飞利浦VTR9100生物ID密码,解锁声音记忆这么多年来,数学界有哪些经典的数学题?Java对象为啥要实现Serializable接口?M3芯片已经正在开发中2023年底亮相北汽新能源蓝谷园区分布式光伏发电项目招标公告陈晨两大赛道拥有十年周期行情明年市场重点或在稀土永磁用过MacBookPro后,我们体会到了苹果的ampampq惠普战66笔记本怎么样?工作用?二手机从12999元降到2368元,512GB和鸿蒙OS,奢智能手机是谁发明的?为啥大家都不愿意换手机?其实就是穷为什么俄罗斯不怕芯片卡脖子?

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利