mybatis insert返回主键_MyBatis最佳实践

传参尽量不要传Map,尽量明确参数类型

用Map传参的第一个(也是最大的一个)弊端就是:这会导致后续接手和维护的人对于代码传的参数不是很清楚,尤其是随着sql量及项目复杂度的增加,带来很大的不确定性也随之增加,非常不利于后续的维护。

db查询的字段名要与结果实体的属性名一致

即sql里返回的字段名要与结果实体的属性名要一致,否则业务代码里是获取到的查询结果会为空。

如果不一致,则有3种解决方案:

  • 方案一:在sql里直接通过AS指定别名

即在查询sql里,为每个查询字段都通过AS指定一个别名,并采用resultType,以关联对应结果实体,如:

a4ccbfc2de625fd1e9b5690b4be06f78.png

  • 方案二:使用MyBatis的驼峰转换配置

即在application.yml里按照如下配置,这样即使db 字段名与配置resultType实体的属性名不完全一致也能自动匹配,但前提是配置resultType实体的属性名要严格遵循驼峰命名方式:

mybatis :  configuration :    map-underscore-to-camel-case : true
  • 方案三:通过来映射字段

即先定义好一个Map,在该Map里配置每个db字段对应的实体属性,如:

7d5733b16446cd0d5c99654d5dbc5edc.png

然后,在后续的sql里配置resultMap,以采用该Map作为结果映射,如:

7920d7dc692adef69ca04f61aa0bce9f.png

mybatis返回MySQL自增主键

获取MySQL的自增主键有以下两种方式:

方式一,使用 useGeneratedKeys + keyProperty 属性

<insert id="insert" parameterType="Person" useGeneratedKeys="true" keyProperty="id">    INSERT INTO person(name, pswd)    VALUE (#{name}, #{pswd})insert>

方式二,使用 `` 标签

<insert id="insert" parameterType="Person" useGeneratedKeys="true" keyProperty="id">    <selectKey keyProperty="id" resultType="long" order="AFTER">        SELECT LAST_INSERT_ID()    selectKey>    INSERT INTO person(name, pswd)    VALUE (#{name}, #{pswd})insert>

第一种方式比较常用。但返回值并不是主键id,而是1和0,分别表示插入成功和失败。

mybatis插入成功之后会将主键自增ID封装到对象中,比如上面的例子,直接使用 person.getId()取ID即可。

尽量自动生成相关实体类及mapper文件

使用MyBatis,工作量最大的就是维护Mapping的映射文件,由于手动书写很容易出错,推荐使用自动化的插件来自动生成对应的实体类、Mapper接口、Mapper.xml等,尤其是当表结构有变化时,能大大降低纯手工维护带来的出错概率。

目前idea也有一些自动生成插件、mybatis-gernerator官方则提供了maven插件,都能实现这些功能,但推荐使用后者,因为可配置化程度更高。

自己定义的sql与自动生成的sql相分离

即通过mybatis-gernerator插件或一些ide插件自动生成的sql要与开发人员自定义的的sql分别放在不同的mapper.xml,便于维护。如果放在同一个mapper.xml,则每次自动生成后,由于还惨杂了自定义的sql,所以依旧得去一个个检查。如果分开来放,则只需要检查自定义sql是否需要修改即可,减少后续的维护工作量。

a8b83835f89d40387423e0a3400fc399.png

若where条件灵活多变,推荐使用Example

比起mapper的if标签,Example方式可以省去很多where条件编写的工作量,也非常便于维护,尤其是表结构有变化时。

注:MyBatis的Example方式非常接近于JPA的面向实体属性的db操作。

尽量使用`#{}`,尽量不用`${}`

为减少SQL注入风险,除非要在sql里动态注入列名表名,否则尽量不要使用使用${}。

较长的sql片段尽量抽离出来作为公共sql

如下所示,若有多处需要查询相同的字段时,则可将这些字段专门剥离出来再引入回去,以提升sql的复用性。同理,一些较长的where条件也可以这样。比如:

<sql id="Base_Column_List">  id, name, address, age, create_time, create_by, update_time, update_bysql>

然后在后续的sql里,通过include引入即可

06473abbd2e6d068495b74c2cf2b9b20.png

对于sql中的固定数值或字符串,建议在mapper文件中使用ongl常量方式引用

即具体的常量值定义在Java代码中(比如放在专门的常量类或枚举类中),在mapper文件中直接引用常量名即可,便于维护。

  • 引用枚举:'${@全路径名@枚举值.get属性()}',则会解析出枚举值的属性常量值,放入sql语句中。(这里单引号''是因为${}占位符只是把值给填充进去,要表示字符串的话,加上单引号)

  • 引用常量:'${@全路径名@常量值}',会解析出常量值,放入sql语句中。

注:方法、属性等也可以解析出来,就如同:类.静态属性、类.静态方法( )。

假设有常量类和常量Constant.STATUS_OK,在Mapper.xml中可这样来引用:

<if test=year==@com.xxx.test.Consant@STATUS_OK>  select * from table_xif>

更多关于MyBatis的最佳实践,后续会不断更新补充。

也欢迎各位小伙一起探讨交流(tom_kang@qq.com),把各自在使用MyBatis过程中的一些踩坑经历、最佳实践分享出来。


- 往期回顾 - JPA最佳实践JPA踩坑系列之save方法JPA踩坑系列之save方法(二) 浅谈Kafka的多线程消费的设计谈谈通用对账平台的业务架构设计 浅谈Kafka的多线程消费的设计(二)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值