MyBatis结果集映射
前面的例子中,数据库中字段或者字段别名与持久化类中成员变量名保持一致,如果二者并不对应,可以通过映射,将不一致的对应起来。
简单的结果集映射
在之前的User类中新添加成员变量createDate(Date)和updateDate(Date),数据库中添加字段create_date(timestamp)和update_date(timestamp),下面实现二者的映射。
在映射文件中使用resultMap标签。
<sql id="common_field" > ${user}.id,${user}.account,${user}.password,${user}.user_name,${user}.create_time,${user}.update_time </sql> <resultMap type="self.exercise.bean.User" id="BaseResultMap"> <result column="create_time" jdbcType="TIMESTAMP" property="createDate"/> <result column="update_time" jdbcType="TIMESTAMP" property="updateDate"/> </resultMap> <select id="load" resultMap="BaseResultMap" parameterType="int"> select <include refid="common_field"> <property name="user" value="user"/> </include> from web_user user where id=${id} </select>
sql标签中内容为提取出的公共字段。
resultMap标签有一个属性 autoMapping,默认值为true;当数据库字段和类中成员名相同时,不必在result标签中手动映射;
result标签中有属性javaType,用于指定类中成员的类型,可以省略;用于指定数据库字段类型的jdbcType必须为大写形式,常见的类型对应关系:
javaType jdbcType int INTEGER String VARCHAR
... ... java.util.Date TIMESTAMP
映射关联属性
如果一个表通过外键与另一个表相关联,在查询一个表信息要求关联另一个表的信息,映射文件中的结果集该如何映射?
新建一个Role角色类,并生成get、set、toString方法。
public class Role { private int role_id; private String role_name; }
在数据库中新建role表,字段与Role对应,user表中新添外键与role表关联。
在User类中添加新的变量Role对象、以及fk_role_id外键,要求在查询user信息时通过外键查询出user对应的角色信息,存到变量Role对象中。
public class User { private String account; private int fk_role_id; private int id; private String password; private Role role; private String user_name; }
现欲查询用户信息,并且附带用户的角色,代码如何实现呢?
<resultMap type="self.exercise.bean.User" id="UserWithRoleMapper"> <id property="id" column="id" jdbcType="INTEGER"/> <result property="account" column="account" jdbcType="VARCHAR"/> <result property="password" column="password" jdbcType="VARCHAR"/> <result property="user_name" column="user_name" jdbcType="VARCHAR"/> <result property="fk_role_id" column="fk_role_id" jdbcType="INTEGER"/> <association property="role" javaType="self.exercise.bean.Role" select="getRoleByfk" column="fk_role_id" > <id property="role_id" column="role_id" jdbcType="INTEGER"/> <result property="role_name" column="role_name" jdbcType="VARCHAR"/> </association> </resultMap> <select id="userWithRole" resultMap="UserWithRoleMapper" parameterType="int"> select * from web_user where id=#{id} </select> <select id="getRoleByfk" parameterType="int" resultType="self.exercise.bean.Role"> select role_id,role_name from role where role_id=#{id} </select>
上述代码中,resultMap为User类的结果集映射;两个查询语句分别查询user和user对应的角色信息。
在结果集映射中,Role对象用assocation标签实现映射。property为User类中的属性role,javaType指定role类型,select指定查询角色信息的sql语句,column指定外键值,assocation子标签可以实现role表和Role对象的映射;
接口中的方法声明为User uerWithRole(@Param("id") int user_id);
这样先查询出user表中的信息,assocation获取了外键和select语句的id,执行语句查询出对应的角色信息,将结果映射到Role对象中。
改进
Role对象为一个自定义对象,可能其他查询语句中也会有查询role表的操作,如果role表中的字段很多,每次查询role信息都要重新实现一次结果集映射(虽然字段名和类属性名相同可以实现自动映射,但要考虑到不一致的情况),所以可以将role信息也用结果集映射,需要时直接引用结果集即可。
<mapper namespace="self.exercise.dao.RoleDao"> <resultMap type="self.exercise.bean.Role" id="baseRoleMapper"> <id property="role_id" column="role_id" jdbcType="INTEGER"/> <result property="role_name" column="role_name" jdbcType="VARCHAR"/> </resultMap> </mapper>
<resultMap type="self.exercise.bean.User" id="UserWithRoleMapper"> <id property="id" column="id" jdbcType="INTEGER"/> <result property="account" column="account" jdbcType="VARCHAR"/> <result property="password" column="password" jdbcType="VARCHAR"/> <result property="user_name" column="user_name" jdbcType="VARCHAR"/> <result property="fk_role_id" column="fk_role_id" jdbcType="INTEGER"/> <association property="role" javaType="self.exercise.bean.Role" resultMap="self.exercise.dao.RoleDao.baseRoleMapper" /> </resultMap> <select id="userWithRole" resultMap="UserWithRoleMapper" parameterType="int"> select u.*,r.* from web_user u left join role r on u.id = r.role_id where id=#{id} </select>
之前的sql语句需要执行两条,现精简为一条。