请关注知了堂学习社区:知了学习
resultMap:用于解决实体类中属性和表字段名不相同的问题
属性说明:
- id属性 ,resultMap标签的标识。
- type属性 ,返回值的全限定类名,或类型别名。
- autoMapping属性 ,值范围true(默认值)|false, 设置是否启动自动映射功能,自动映射功能就是自动查找与字段名小写同名的属性名,并调用setter方法。而设置为false后,则需要在resultMap内明确注明映射关系才会调用对应的setter方法
子元素说明:
- id:用于设置主键字段与领域模型属性的映射关系
- result:用于设置普通字段与领域模型属性的映射关系
id、result语句属性配置细节:
- property:需要映射到JavaBean 的属性名称。
- column:数据表的列名或者标签别名。
- javaType:一个完整的类名,或者是一个类型别名。
在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体类属性名不相同的冲突。resultMap.
一、resultMap
1.1 数据库准备:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(50) DEFAULT NULL,
`userAge` int(11) DEFAULT NULL,
`userAddress` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
-- ----------------------------
-- 添加几条测试数据
-- ----------------------------
Insert INTO `user` VALUES ('1', 'summer', '100', 'shanghai,pudong');
1.2 定义实体类
package com.zlt.model;
public class User {
private Integer id;
private String userName;
private String userAddress;
private String userAge;
//get,set,toString方法
}
1.3 书写resultMap和sql语句
定义sql映射xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zlt.mapping.UserMapper">
<!-- User自身的属性与数据表字段的映射 property:实体类属性,column查询结果(或数据表)字段名 -->
<resultMap type="com.zlt.model.User" id="resultUserList">
<id property="id" column="id"/>
<result property="userName" column="userName"/>
<result property="userAge" column="userAge"/>
<result property="userAddress" column="userAddress"/>
</resultMap>
<select id="getUserById" parameterType="java.lang.Integer" resultMap="resultUserList">
select * from user where id=#{id};
</select>
</mapper>
基于接口实现-接口代码:
package com.zlt.mapping;
import com.zlt.model.User;
public interface UserMapper {
//通过ID查询信息
public User getUserById(Integer id);
}
注意:配置文件的mapper标签中的namespace的值就是接口的路径。
1.4 测试类:
package com.zlt.test;
import org.apache.ibatis.session.SqlSession;
import com.zlt.mapping.UserMapper;
import com.zlt.model.User;
import com.zlt.util.MyBatisUtil;
public class Test {
public static void main(String[] args) {
new Test().getUserById();
}
public void getUserById() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);
System.out.println(user);
}
}
//运行结果:User [id=1, userName=summer, userAddress=shanghai,pudong, userAge=100]
二、association联合
联合元素用来处理“一对一”的关系。需要指定映射的Java实体类的属性,属性的javaType(通常MyBatis 自己会识别)。对应的数据库表的列名称。如果想覆写的话返回结果的值,需要指定typeHandler。
不同情况需要告诉MyBatis 如何加载一个联合。MyBatis 可以用两种方式加载:
- select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活
- resultsMap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型
例如:一篇文章对应一个作者
首先定义好文章中的作者:private User user;//对应用户
2.1 使用select实现联合查询
例子:文章实体类(Article)有作者属性,通过联合在得到一个文章实体时,同时映射出作者实体。
2.1.1 配置articleMapper.xml
<!-- 定义JavaBean的属性与数据表的列之间的映射 -->
<resultMap type="com.zlt.model.Article" id="resultUserArticleList">
<!-- 处理查询结果的字段名和实体类属性名不匹配 -->
<id property="id" column="aid"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
<!-- association处理1-1的关系 -->
<!--注意:这种方式javaType必须指定,表示user的类型是User,否则会报错 -->
<association property="user" column="aid"
select="getUserById" />
</resultMap>
<resultMap type="com.zlt.model.User" id="resultUserList">
<id property="id" column="id"/>
<result property="userName" column="userName"/>
<result property="userAge" column="userAge"/>
<result property="userAddress" column="userAddress"/>
</resultMap>
<!-- SQL语句中以"#{}"的形式引用参数 -->
<!-- 这儿将user表的id取了别名:aid -->
<select id="getArticles" parameterType="java.lang.Integer" resultMap="resultUserArticleList">
SELECT article.id aid,article.title,article.content FROM article WHERE id = #{article_id};
</select>
<select id="getUserById" parameterType="java.lang.Integer" resultMap="resultUserList">
select id,userName,userAge,userAddress from user where id=#{id};
</select>
2.1.2接口:
package com.zlt.mapping;
import java.util.List;
import com.zlt.model.Article;
public interface ArticleMapper {
//使用resultMap联合
public Article getUserArticles(Integer article_id);
//使用select联合
public Article getArticles(Integer article_id);
}
2.1.3 测试:
@org.junit.Test
public void getUserArticles() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
ArticleMapper articleMapper = sqlSession.getMapper(ArticleMapper.class);
Article artList = articleMapper.getArticles(1);
System.out.println(artList);
}
这种方式简单并且容易理解,不过它却有个致命的缺点,那就是如果查询的为大型数据集合和列表的情况下,那么所需要查询的SQL语句条数的数量会是惊人的。即是:“N+1”的情况,即需要对返回回来的N条数据进行细节添加
2.2 使用resultMap实现联合
与上面同样的功能,查询班级,同时查询器班主任。需在association中添加resultMap
<!-- 定义JavaBean的属性与数据表的列之间的映射 -->
<resultMap type="com.zlt.model.Article" id="resultUserArticleList">
<!-- 处理查询结果的字段名和实体类属性名不匹配 -->
<id property="id" column="aid"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
<!-- association处理1-1的关系 -->
<!--注意:这种方式javaType必须指定,表示user的类型是User,否则会报错 -->
<association property="user" resultMap="resultUserList" />
</resultMap>
<resultMap type="com.zlt.model.User" id="resultUserList">
<id property="id" column="id"/>
<result property="userName" column="userName"/>
<result property="userAge" column="userAge"/>
<result property="userAddress" column="userAddress"/>
</resultMap>
<!-- SQL语句中以"#{}"的形式引用参数 -->
<!-- 这儿将user表的id取了别名:aid -->
<select id="getUserArticles" parameterType="java.lang.Integer" resultMap="resultUserArticleList">
SELECT us.id,us.userName,us.userAddress,art.id aid,art.title,art.content,us.userAge
FROM article art LEFT JOIN USER us ON art.userid = us.id
WHERE art.id=#{article_id};
//输出结果:Article [id=1, title=test_title, content=test_content, user=User [id=1, userName=summer, userAddress=shanghai,pudong, userAge=100]]