MyBatis之前一直都在使用resultType,现在来学习一下使用resultMap。
直接这样简单的分析一下吧:
- 有一个用户
- 这个用户有一个角色表来表示他是客户,而不是管理员
- 这个用户有两本书
原本我如果碰到这种情况,角色可能会通过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] ] ]
最新评论