巴拉巴拉
小魔仙

MyBatis——resultMap

MyBatis之前一直都在使用resultType,现在来学习一下使用resultMap。

直接这样简单的分析一下吧:

  1. 有一个用户
  2. 这个用户有一个角色表来表示他是客户,而不是管理员
  3. 这个用户有两本书

原本我如果碰到这种情况,角色可能会通过left join 查询相应属性,拥有的两本书则只能先查出角色的id,然后通过角色的id再去查他拥有哪些书。

现在学习了resultMap之后,可以直接在User实体里面设置一个List<Book>来直接存放他有哪些书啦。

现在来个放出案例:)
这个案例我没有集成Spring,只是一个单纯的MyBatis项目^_^
本机操作环境:

  • win7 x64
  • jdk 1.8
  • mysql 5.5
  • mybatis-3.2.1.jar
  • mysql-connector-java-5.1.34.jar

首先,先给出数据库的初始数据:

CREATE DATABASE IF NOT EXISTS `mybatis`
USE `mybatis`;

CREATE TABLE IF NOT EXISTS `user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(50) DEFAULT NULL,
  `user_age` int(11) DEFAULT NULL,
  `role_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

INSERT INTO `user` (`user_id`, `user_name`, `user_age`, `role_id`) VALUES
	(1, '陆逊', 25, 1);
	
CREATE TABLE IF NOT EXISTS `role` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(50) NOT NULL,
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

INSERT INTO `role` (`role_id`, `role_name`) VALUES
	(1, '用户'),
	(2, '客服');


CREATE TABLE IF NOT EXISTS `book` (
  `book_id` int(11) DEFAULT NULL,
  `book_name` varchar(50) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `book` (`book_id`, `book_name`, `user_id`) VALUES
	(1, '上下五千年', 1),
	(2, 'Mybatis', 1);

来预览一下数据库的结构吧:

mysql> select * from user;
+---------+-----------+----------+---------+
| user_id | user_name | user_age | role_id |
+---------+-----------+----------+---------+
|       1 | 陆逊       |       25 |       1 |
+---------+-----------+----------+---------+
1 row in set (0.00 sec)

mysql> select * from role;
+---------+-----------+
| role_id | role_name |
+---------+-----------+
|       1 | 用户       |
|       2 | 客服       |
+---------+-----------+
2 rows in set (0.00 sec)

mysql> select * from book;
+---------+-----------------+---------+
| book_id | book_name       | user_id |
+---------+-----------------+---------+
|       1 | 上下五千年        |       1 |
|       2 | Mybatis         |       1 |
+---------+-----------------+---------+
2 rows in set (0.00 sec)

 

放出项目的结构

MyBtaisProject
┃
┗━src
	┃
	┣━com.againfly
	┃		┃
	┃		┣━main
	┃		┃	┃
	┃		┃	┗━Main.java
	┃		┣━mapper
	┃		┃	┃
	┃		┃	┗━AgainFlyMapper.java
	┃		┣━pojo
	┃		┃	┃
	┃		┃	┣━Book.java
	┃		┃	┃
	┃		┃	┣━Role.java
	┃		┃	┃
	┃		┃	┗━User.java
	┃		┗━xml
	┃			┃
	┃			┗━AgainFlyMapper.xml
	┃
	┗━Configuration.xml

首先我们先来看一下MyBatis的配置文件Configuration.xml

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<typeAliases>
		<typeAlias alias="User" type="com.againfly.pojo.User" />
		<typeAlias alias="Role" type="com.againfly.pojo.Role" />
		<typeAlias alias="Book" type="com.againfly.pojo.Book" />
	</typeAliases>

	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>

	<mappers>
		<mapper resource="com/againfly/xml/AgainFlyMapper.xml" />
	</mappers>
</configuration>

typeAliases里面设置了我们需要的三个实体类,使用Alias可以很方便让我们在Mapper中使用,而不需要使用很长的类完整名称。
environments里面配置了数据库的信息,大家按照自己的情况配置就好
mappers是映射的Mapper的xml配置文件,里面存放着sql语句

############################################################

接着我们需要三个实体类:
三个实体类我分别做了三种不同的方式。
User有一个默认的构造方法和一个带Id和Name的构造方法
Role有一个默认的构造方法和一个带Id的构造方法
Book只有默认的构造方法。
所有贴出的代码都省略了get和set方法,有必要的话可以加上toString方法,可以很方便的查看输出对象的情况。

package com.againfly.pojo;

import java.util.List;

public class User {
	private int userId;
	private String userName;
	private int age;
	private int roleId;

	private Role role;

	private List<Book> books;
	
	public User() {
	}
	
	public User(Integer userId, String userName) {
		this.userId = userId;
		this.userName = userName;
	}
	/****** hide get()/set() and toString() method *******/

}

eg:User实体类里面多放了一个Role角色属性和List<Book>书籍集合类。

package com.againfly.pojo;

public class Role {
	private int roleId;
	private String roleName;
	
	public Role() {
	}
	
	public Role(Integer roleId) {
		this.roleId = roleId;
	}

	/****** hide get()/set() and toString() method *******/
}
package com.againfly.pojo;

public class Book {
	private int bookId;
	private String bookName;

	/****** hide get()/set() and toString() method *******/

}

 

需要一个接口来实现我们的操作:

package com.againfly.mapper;

import com.againfly.pojo.User;

public interface AgainFlyMapper {
	User getUser(int sysId);
}

 

开始配置我们的Mapper

<?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.againfly.mapper.AgainFlyMapper">

	<resultMap type="User" id="userMap">
		<constructor>
			<idArg column="user_id" javaType="Integer"/>
			<arg column="user_name" javaType="String"/>
		</constructor>
		<result property="age" column="user_age"/>
		<result property="roleId" column="role_id"/>
		<association property="role" column="role_id" javaType="Role" select="selectRole"/>
		<collection property="books" column="user_id" javaType="ArrayList" select="selectBook"/>
	</resultMap>
	
	<resultMap type="Role" id="roleMap">
		<constructor>
			<idArg column="role_id" javaType="Integer"/>
		</constructor>
		<result property="roleName" column="role_name"/>
	</resultMap>
	
	<resultMap type="Book" id="bookMap">
		<id property="bookId" column="book_id"/>
		<result property="bookName" column="book_name"/>
	</resultMap>
	
	<select id="getUser" parameterType="int" resultMap="userMap">
		select user_id,user_name,user_age,role_id 
		from user
		where user_id = #{userId}
	</select>
	
	<select id="selectRole" parameterType="int" resultMap="roleMap">
		select role_id,role_name 
		from role
		where role_id = #{roleId}
	</select>
	
	<select id="selectBook" parameterType="int" resultMap="bookMap">
		select book_id,book_name
		from book
		where user_id = #{user_id}
	</select>
	
</mapper>

现在来解释一下Mapper里面的一些东西

  • resultMap
    ——id,resultMap的标示
    ——type,返回的对象类型或者别名
  • constructor,走这个对象的构造方法,里面设置的顺序要严格的和构造方法中的顺序保持一致。
    ——idArg,主键参数,设置主键可以提高性能
    ——arg,普通参数
  • result,设置普通属性
  • property,实体类中的属性名
  • column,数据库中的字段名
  • association,映射单个复杂对象
  • collection,映射多个复杂对象

其实这个时候发现使用resultMap之后,是可以通过这样的配置来完成字段名和实体类属性名不一致的情况,而不需要使用 book_name as `bookName` 这样的别名方式了。
<result property="bookName" column="book_name"/>

我们来测试我们刚刚写好的resultMap测试一下

package com.againfly.main;

import java.io.IOException;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.againfly.mapper.AgainFlyMapper;
import com.againfly.pojo.User;

public class Main {

	private SqlSessionFactory sqlSessionFactory;
	private Reader reader;
	private SqlSession session;
	
	@Before
	public void init() throws IOException{
		reader = Resources.getResourceAsReader("Configuration.xml");
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		session = sqlSessionFactory.openSession();
	}
	
	@After
	public void destory(){
//		session.commit();
//		session.rollback();
		session.close();
	}
	
	@Test
	public void test(){
		AgainFlyMapper mapper = session.getMapper(AgainFlyMapper.class);
		User user = mapper.getUser(1);
		System.out.println(user.toString());
	}
	
}
User [
	userId=1, 
	userName=陆逊, 
	age=25, 
	roleId=1, 
	role=Role [roleId=1, roleName=用户], 
	books=[
		Book [bookId=1, bookName=上下五千年], 
		Book [bookId=2, bookName=Mybatis]
	]
]

 

赞(0) 打赏
如果文章对你有帮助,欢迎你来评价反馈。AgainFly » MyBatis——resultMap
标签:

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  • Q Q(选填)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏