MyBatis 自动映射

xiaoxiao2021-02-28  15

0x00:引子

在 MyBatis 的映射配置文件中,select 标签查询配置结果集时使用过 resultType 属性,当在 resultType 中定义一个 Java 包装类时,如果 sql 语句查询的结果中有列名与该 Java 包装类中的属性名一致,则该字段就会被映射到该属性上。这里用到的就是 MyBatis 的自动映射功能,

当 sql 语句查询出结果时,如果对应输出配置的 Java 包装类中有相同名称的属性,且拥有 set 方法,则该结果就会被自动映射。

0x01:原理

MyBatis 的自动映射功能是建立在 resultMap 基础之上的。resultType 属性自动映射的原理是,当 sql 映射输出配置为 resultType 时,MyBatis 会生成一个空的 resultMap,然后指定这个 resultMap 的 type 为指定的 resultType 的类型,接着 MyBatis 检测查询结果集中字段与指定 type 类型中属性的映射关系,对结果进行自动映射。

在 MyBatis 全局配置文件中,在 setting 标签内设置自动映射模式:

<setting name="autoMappingBehavior" value="PARTIAL"/>

0x02:配置

在 MyBatis 中,自动映射有三种模式,分别是 NONE、PARTIAL、FULL。其中 NONE 表示不启用自动映射,PARTIAL 表示只对非嵌套的 resultMap 进行自动映射,FULL 表示对所有的 resultMap 都进行自动映射。默认的自动映射模式为 PARTIAL。

0x03:拓展

在 sql 查询结果中,如果只有部分字段与输入配置类型中的属性名称不一样,则可以仅在 resultMap 中指定不一样的字段对应的输出类型的属性,其他的则会直接进行自动映射。

例如以下示例,Java 包装类中用户名属性为 username,而在 t_user 表中用户名的字段名为 name,这里需要手动映射 name 字段,其他的属性可以通过默认的自动映射机制来映射:

<resultMap type="cn.com.mybatis.pojo.User" id="UserResult"> <result property="username" column="name"/> </resultMap> <select id="findUserById" parameterType="java.lang.Long" resultMap="UserResult"> select id,name,email from t_user where id=#{id} </select>

在 User 类中,包含了手动映射的 username 属性和自动映射的 id、email 属性。

如果在某些 resultMap 中不想使用自动映射,则可以单独在该 resultMap 中设置 autoMapping 的属性为 false,此时该 resultMap 仅映射指定的映射字段:

<select id="findUserById" parameterType="java.lang.Long" resultMap="UserResult" autoMapping="false"> select id,name,email from t_user where id=#{id} </select>

当配置了 autoMapping 属性后,就会忽略全局配置文件中的 autoMappingBehavior 映射模式。

0x04:关于 FULL

关于 FULL 模式,应该谨慎使用,该模式不管 resultMap 是嵌套的还是非嵌套的,都会进行自动映射,这可能会造成某些嵌套属性与查询结果的字段名一致而误被自动映射,例如以下示例:

<resultMap id="replyResult" type="cn.com.mybatis.pojo.Reply"> <association property="user" resultMap="userResult"/> </resultMap> <resultMap id="userResult" type="cn.com.mybatis.pojo.User"> <result property="username" column="name"/> </resultMap> <select id="queryReplyInfo" parameterType="java.lang.Long" resultMap="replyResult"> select R.id,R.title,R.info,U.name form reply R left join t_user U on R.user_id = U.id where R.id=#{id} </select>

以上示例加载了一个评论 Reply 和该评论的作者 User 信息,User 并不要求映射 id 属性,如果这个时候设置了自动映射模式为 FULL,那么就会将从结果中取出的评论 Reply 的 id 值赋给嵌套的 resultMap 中 User 的 id,造成数据混乱。

0x05:总结

MyBatis 中的 resultMap 映射当返回的字段名与类中字段名一致时,默认配置是自动映射。通过 autoMappingBehavior 来配置,配置方式有三种,NONE、PARTIAL、FULL,其中 NONE 代表不启用自动映射,PARTIAL 代表只对非嵌套的 resultMap 进行映射,FULL 代表对所有的 resultMap 都进行映射。而对于 FULL 配置,用时需要谨慎,避免造成数据混乱的情况。


                                                                        公众号推荐:aFa攻防实验室

                         分享关于信息搜集、Web安全、内网安全、代码审计、红蓝对抗、Java、Python等方面的东西。

                                                                         

转载请注明原文地址: https://www.6miu.com/read-2449969.html

最新回复(0)