ResultMap

在实际的开发中,数据库不总是我们希望看到的样子。比如我们希望User的主键是id但是数据库偏偏喜欢叫它u_id,这样一来原先的resultType似乎就失效了,不带这么玩的,整个人都不好了。

于是mybatis给出了他的方案——resultMap。把我们从复杂的命名问题中解救出来~~~

在上一篇中已经用mybatis generator生成好了一个BlogMapper.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="pro.app.inter.BlogMapper" >
<resultMap id="BaseResultMap" type="pro.app.model.Blog" >
<id column="b_id" property="bId" jdbcType="INTEGER" />
<result column="b_title" property="bTitle" jdbcType="VARCHAR" />
<result column="b_content" property="bContent" jdbcType="VARCHAR" />
<result column="user_id" property="userId" jdbcType="INTEGER" />
</resultMap> <sql id="Base_Column_List" >
b_id, b_title, b_content, user_id
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from blog
where b_id = #{bId,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from blog
where b_id = #{bId,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="pro.app.model.Blog" >
<selectKey resultType="java.lang.Integer" keyProperty="bId" order="AFTER" >
SELECT LAST_INSERT_ID()
</selectKey>
insert into blog (b_title, b_content, user_id
)
values (#{bTitle,jdbcType=VARCHAR}, #{bContent,jdbcType=VARCHAR}, #{userId,jdbcType=INTEGER}
)
</insert>
<insert id="insertSelective" parameterType="pro.app.model.Blog" >
<selectKey resultType="java.lang.Integer" keyProperty="bId" order="AFTER" >
SELECT LAST_INSERT_ID()
</selectKey>
insert into blog
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="bTitle != null" >
b_title,
</if>
<if test="bContent != null" >
b_content,
</if>
<if test="userId != null" >
user_id,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="bTitle != null" >
#{bTitle,jdbcType=VARCHAR},
</if>
<if test="bContent != null" >
#{bContent,jdbcType=VARCHAR},
</if>
<if test="userId != null" >
#{userId,jdbcType=INTEGER},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="pro.app.model.Blog" >
update blog
<set >
<if test="bTitle != null" >
b_title = #{bTitle,jdbcType=VARCHAR},
</if>
<if test="bContent != null" >
b_content = #{bContent,jdbcType=VARCHAR},
</if>
<if test="userId != null" >
user_id = #{userId,jdbcType=INTEGER},
</if>
</set>
where b_id = #{bId,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="pro.app.model.Blog" >
update blog
set b_title = #{bTitle,jdbcType=VARCHAR},
b_content = #{bContent,jdbcType=VARCHAR},
user_id = #{userId,jdbcType=INTEGER}
where b_id = #{bId,jdbcType=INTEGER}
</update>
</mapper>

在文件的开头位置,就能够发现一个名为BaseResultMap的resultMap标签。在这个标签当中我们可以发现几个子标签。这几个子标签对通过column和property属性将数据库字段和model对应类型关联起来。而<id/>标签代表这个model类的属性对应的数据库字段为这张表的主键。定义完成这个BaseResultMap之后,我们就可以在后面的标签对中使用它作为返回的结果使用。 这里可以注意到select的属性resultMap="BaseResultMap" 。返回的数据通过resultMap被封装成了相应的对象,如果返回的数据是多条,mybatis也会自动将结果集转换为List集合。

这里还可以关注下resultMap下的sql标签对,在这个标签对中可以写入数据库的字段名称。在CRUD的xml文件中使用<include/>标签引用这它,在数据库需要修改的时候,我们就不用去修改这个配置文件下每一个sql语句。

数据关联

有人会说。这样resultMap和resultType有什么区别!还要多写这么一堆配置,这不是吃饱了撑着么!!!真的是这个样子?

我们之前设计了两张表,一个用户表和一个博客列表,一个用户可以有多篇博客吧,一篇博客只有一个作者。现在就让resultMap帮助我们把数据关联起来~

先给表Blog添加几条数据

 INSERT INTO `blog`.`blog` (`b_id`, `b_title`, `b_content`, `user_id`) VALUES ('', '', 'mybatis001', '');
INSERT INTO `blog`.`blog` (`b_id`, `b_title`, `b_content`, `user_id`) VALUES ('', '', 'mybatis002', '');
INSERT INTO `blog`.`blog` (`b_id`, `b_title`, `b_content`, `user_id`) VALUES ('', '', 'mybatis003', '');
INSERT INTO `blog`.`blog` (`b_id`, `b_title`, `b_content`, `user_id`) VALUES ('', '', 'mybatis004', '');
INSERT INTO `blog`.`blog` (`b_id`, `b_title`, `b_content`, `user_id`) VALUES ('', '', 'mybatis005', '');

在此之前我们需要再定义一个BlogVo类,并继承Blog类,然后添加一个User类型属性user。

 package pro.app.model;

 public class BlogVo extends Blog{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

接着在BlogMapper.xml中添加一个resultMap。

 <resultMap id="BaseResultMapWithUser" type="pro.app.model.BlogVo" >
<id column="b_id" property="bId" jdbcType="INTEGER" />
<result column="b_title" property="bTitle" jdbcType="VARCHAR" />
<result column="b_content" property="bContent" jdbcType="VARCHAR" />
<association property="user" javaType="pro.app.model.User">
<id column="user_id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="INTEGER" />
</association>
</resultMap>

在resultMap中通过子标签association,我们将外键与对应的model类型对应起来。用association中的property属性对应java属性的用户。association下的子标签id对应blog表中的外键,这也是数据关联的关键!接着再给这个文件添加一个select标签。

  <select id="selectByPrimaryKeyWithUser" resultMap="BaseResultMapWithUser" parameterType="java.lang.Integer" >
select *
from blog b
join user u
on b.user_id=u.id
where b.b_id= #{id,jdbcType=INTEGER}
</select>

ok,让我们在BlogMapper.java里添加一个selectByPrimaryKeyWithUser()方法。

 package pro.app.inter;

 import org.apache.ibatis.annotations.Param;

 import pro.app.model.Blog;
import pro.app.model.BlogVo; public interface BlogMapper {
int deleteByPrimaryKey(Integer bId); int insert(Blog record); int insertSelective(Blog record); Blog selectByPrimaryKey(Integer bId); int updateByPrimaryKeySelective(Blog record); int updateByPrimaryKey(Blog record); BlogVo selectByPrimaryKeyWithUser(@Param("id")Integer id); }

建立一个测试类来看看效果

 package pro.test;

 import java.io.Reader;

 import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import pro.app.inter.BlogMapper;
import pro.app.model.Blog;
import pro.app.model.BlogVo; public class BlogVoTest {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
static{
try{
reader= Resources.getResourceAsReader("Configuration.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}catch(Exception e){
e.printStackTrace();
}
}
public static SqlSessionFactory getSession(){
return sqlSessionFactory;
}
public static void main(String[] args) {
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper blogs = session.getMapper(BlogMapper.class);
BlogVo bv=blogs.selectByPrimaryKeyWithUser(1);
System.out.println(bv.getUser().getName());
} finally {
session.close();
}
}
}

控制台输出了:

Mybatis

ok!mybatis帮我们把博客的作者选出来了。现在我们来通过作者选出他所有的文章。

同样我们在UserMapper.xml里添加一个resultMap

   <resultMap id="BaseResultMapWithBlogs" type="pro.app.model.UserVo" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="INTEGER" />
<collection property="blogs" ofType="pro.app.model.Blog" column="b_id">
<id column="b_id" property="bId" jdbcType="INTEGER" />
<result column="b_title" property="bTitle" jdbcType="VARCHAR" />
<result column="b_content" property="bContent" jdbcType="VARCHAR" />
</collection>
</resultMap>

这里的resultMap还多个了一个collection标签,顾名思义这表示一个集合,collection的column表示结果集对应的table的主键。现在再添加一个select标签。

     <select id="selectOneWithBlogs" resultMap="BaseResultMapWithBlogs" parameterType="java.lang.Integer">
select *
from blog b
join user u
on b.user_id=u.id
where u.id = #{id,jdbcType=INTEGER}
</select>

在UserDAO.java里添加一个selectOneWithBlogs()方法。

 package pro.app.inter;
import org.apache.ibatis.annotations.Param; import pro.app.model.User;
import pro.app.model.UserVo; public interface UserDAO {
public User selectOne(@Param("id")Integer id); public void insertOne(User user); public void deleteOne(@Param("id")Integer id); public void updateOne(User user); UserVo selectOneWithBlogs(@Param("id")Integer id);
}

新建一个测试类,观察结果。

 package pro.test;

 import java.io.Reader;

 import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import pro.app.inter.UserDAO;
import pro.app.model.Blog;
import pro.app.model.UserVo; public class UserVoTest {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
static{
try{
reader= Resources.getResourceAsReader("Configuration.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}catch(Exception e){
e.printStackTrace();
}
}
public static SqlSessionFactory getSession(){
return sqlSessionFactory;
}
public static void main(String[] args) {
SqlSession session = sqlSessionFactory.openSession();
try {
UserDAO users = session.getMapper(UserDAO.class);
UserVo user=users.selectOneWithBlogs(1);
for(Blog b:user.getBlogs()){
System.out.println(b.getbTitle());
System.out.println(b.getbContent());
}
} finally {
session.close();
}
}
}

控制台输出

mybatis001

mybatis002

mybatis003

mybatis004

mybatis005

bingo!!!用户对应的博客都被选出来了~

总结

通过resultMap 实现数据的关联。

Hello Mybatis 03 数据关联的更多相关文章

  1. MyBatis框架——mybatis插入数据返回主键(mysql、oracle)

    向数据库中插入数据时,大多数情况都会使用自增列或者UUID做为主键.主键的值都是插入之前无法知道的,但很多情况下我们在插入数据后需要使用刚刚插入数据的主键,比如向两张关联表A.B中插入数据(A的主键是 ...

  2. MyBatis总结-实现关联表查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

  3. mybatis框架(6)---mybatis插入数据后获取自增主键

    mybatis插入数据后获取自增主键 首先理解这就话的意思:就是在往数据库表中插入一条数据的同时,返回该条数据在数据库表中的自增主键值. 有什么用呢,举个例子: 你编辑一条新闻,同时需要给该新闻打上标 ...

  4. mybatis插入数据后将其ID返回

    背景 mybatis没有关联保存的功能,所以主从表需要分开保存,这就涉及到主表保存后要再次获取主表ID的环节,以下介绍mybatis插入数据后返回其自增ID的两种方式 方案 1.sql获取 <i ...

  5. 三、mybatis多表关联查询和分布查询

    前言 mybatis多表关联查询和懒查询,这篇文章通过一对一和一对多的实例来展示多表查询.不过需要掌握数据输出的这方面的知识.之前整理过了mybatis入门案例和mybatis数据输出,多表查询是在前 ...

  6. mybatis多对一关联

    mybatis多对一关联查询实现 1.定义实体 定义实体的时候需要注意,若是双向关联,就是说双方的属性中都含有对方对象作为域属性出现, 那么在写toString()方法时需要注意,只让某一方输出即可, ...

  7. EF – 3.EF数据查询基础(下)数据关联

    5.5.1 <关于“数据关联”,你不一定清楚的事> 这讲视频比较全面地介绍了“一对一”.“一对多”和“多对多”三种数据关联类型在关系数据库和Entity Framework数据模型中的实现 ...

  8. 5,SFDC 管理员篇 - 数据模型 - 数据关联

    1,PickList 1,填写基本信息 2, 选择能角色的权限 3,在哪一个层上显示(object 上有多个 Record Type 对应多个层,需要选择在哪一个层显示) 4,Save   2,两个P ...

  9. 微信小程序教学第三章第三节(含视频):小程序中级实战教程:视图与数据关联

    § 视图与数据关联 本文配套视频地址: https://v.qq.com/x/page/z0554wyswib.html 开始前请把 ch3-3 分支中的 code/ 目录导入微信开发工具 首先 首先 ...

随机推荐

  1. IIS 7 Web服务器上部署ASP.NET网站(转)

    IIS 7 Web服务器上部署ASP.NET网站小记 摘自:http://swanmsg.blog.sohu.com/162111073.html 网上查找了很久关于iis7配置asp.net配置问题 ...

  2. First class ,6 examples anlaysisi

    http://www.fgm.cc/learn/ First class ,6 examples anlaysisi <!DOCTYPE html> <!-- To change t ...

  3. Android照片墙加强版,使用ViewPager实现画廊效果

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/12646775 记得关于照片墙的文章我已经写过好几篇了,有最基本的照片墙,有瀑布流模 ...

  4. 46. Permutations 回溯算法

    https://leetcode.com/problems/permutations/ 求数列的所有排列组合.思路很清晰,将后面每一个元素依次同第一个元素交换,然后递归求接下来的(n-1)个元素的全排 ...

  5. 搜索引擎 ElasticSearch 之 步步为营1 【环境搭建&初识ElasticSearch】

    1.下载ElasticSearch a.下载Java环境JDK:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloa ...

  6. AsyncOperation变成同步的代码

    template <typename TResult> TResult PerformSynchronously(Windows::Foundation::IAsyncOperation& ...

  7. CSS伪类选择器

    一.CSS伪类选择器用于给某些选择器添加效果语法规则:选择器:伪选择器例:a:link {color: #FF0000} 未访问的链接 a:visited {color: #00FF00} 已访问的链 ...

  8. 个人博客作业week2——代码复审

    1.代码规范 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 代码规范并不是从官僚制度下产生,它是为了提高项目团队开发效率而产生的一种工具,能够极大的增强代码可读 ...

  9. [置顶]PADS PCB功能使用技巧系列之NO.006- 如何实现OrCAD与PADS Layout同步?

    很多同仁都喜欢用OrCAD画原理图,而PCB Layout则用PADS/PowerPCB,这两者被有些人誉为“黄金组合”,但由于两者并非一套软件,因此如何实现同步亦是需要急待解决的问题... (未完待 ...

  10. alfresco install in linux, and integrated with tesseract ocr

    本文描述在Linux系统上安装Alfresco的步骤: 1. 下载安装文件:alfresco-community-5.0.d-installer-linux-x64.bin 2. 增加执行权限并执行: ...