基于 XML 的 MyBatis 应用
Posted 一起学 Java
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于 XML 的 MyBatis 应用相关的知识,希望对你有一定的参考价值。
一、Mybatis 相关概念(面试点)
对象 / 关系数据库映射(ORM)
ORM全称Object/Relation Mapping:表示对象-关系映射的缩写
ORM完成⾯向对象的编程语⾔到关系数据库的映射。当ORM框架完成映射后,程序员既可以利⽤⾯向对象程序设计语⾔的简单易⽤性,⼜可以利⽤关系数据库的技术优势。ORM把关系数据库包装成⾯向对象的模型。ORM框架是⾯向对象设计语⾔与关系数据库发展不同步时的中间解决⽅案。采⽤ORM框架后,应⽤程序不再直接访问底层数据库,⽽是以⾯向对象的放松来操作持久化对象,⽽ORM框架则将这些⾯向对象的操作转换成底层SQL操作。ORM框架实现的效果:把对持久化对象的保存、修改、删除等操作,转换为对数据库的操作
Mybatis 简介
MyBatis是⼀款优秀的基于ORM的半⾃动轻量级持久层框架,它⽀持定制化SQL、存储过程以及⾼级映射。MyBatis避免了⼏乎所有的JDBC代码和⼿动设置参数以及获取结果集。MyBatis可以使⽤简单的XML或注解来配置和映射原⽣类型、接⼝和 Java 的 POJO (Plain Old Java Objects,普通⽼式Java对 象)为数据库中的记录。
Mybatis 历史
原是apache的⼀个开源项⽬iBatis, 2010年6⽉这个项⽬由apache software foundation 迁移到了google code,随着开发团队转投Google Code旗下,ibatis3.x正式更名为Mybatis ,代码于2013年11⽉迁移到Github。
iBATIS⼀词来源于“internet”和“abatis”的组合,是⼀个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
Mybatis 优势
Mybatis是⼀个半⾃动化的持久层框架,对开发⼈员开说,核⼼sql还是需要⾃⼰进⾏优化,sql和java编码进⾏分离,功能边界清晰,⼀个专注业务,⼀个专注数据。
二、Mybatis 基本应用
1.快速入门
开发步骤
添加 MyBatis 的坐标(Maven依赖)
创建 User 数据表
编写 User实体类
编写映射文件 UserMapper.xml
编写核心配置文件 SqlMapConfig.xml
编写测试类
环境搭建
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--mybatis坐标-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql驱动坐标-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<!--单元测试坐标-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--⽇志坐标-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>创建 User 数据表
新建 Maven 工程,命名为 mybatis_quickStart,添加 Mybatis 的 Maven 依赖
* 编写 User实体类
```java
public class User {
private Integer id;
private String username;
// set、get、toString 方法省略。。。
}
```
* 编写映射文件 UserMapper.xml
```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="user">
<select id="selectList" resultType="com.mfc.entity.User">
select * from user
</select>
</mapper>
```
* 编写核心配置文件 SqlMapConfig.xml
```xml
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- default 指定默认环境的名称 -->
<environments default="dev">
<!-- id指定当前环境名称 -->
<environment id="dev">
<!-- 事务管理类型,交由 JDBC 管理事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 指定当前数据源类型是连接池 -->
<dataSource type="POOLED">
<!-- 数据源配置的基本参数 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
```
* 编写测试类
```java
@org.junit.Test
public void test() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("user.selectList");
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
```
2.增删改查
MyBatis 的插入操作
插入语句使用 insert 语句
在映射文件中使用 parameterType 属性指定要插入的数据类型
SQL 语句中使用 #{实体属性名} 方式引用实体中的属性值
插入操作使用的 API 是 sqlSession.insert("命名空间.id", 实体对象);
插入操作设计数据库数据变化,所以要使用 sqlSession 对象显示的提交事务,即 sqlSession.commit()。(也可以在创建 SqlSession 时设置自动提交事务)
编写 UserMapper.xml 映射文件
<mapper namespace="user">
<insert id="insertUser" parameterType="com.mfc.entity.User">
insert into user values(#{id},#{username})
</insert>
</mapper>编写插入实体 User 的代码
@org.junit.Test
public void testInsert() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(4);
user.setUsername("FanchengMeng");
sqlSession.insert("user.insertUser",user);
sqlSession.commit();
sqlSession.close();
}插入操作注意的问题
SqlSession sqlSession = sqlSessionFactory.openSession(true);
Mybatis 的删除操作
删除语句使用 delete 标签
Sql 语句中使用 #{任意字符串} 方式引用传递的单个参数
删除操作使用的 API 是 sqlSession.delete("命名空间.id", Object);
编写 UserMapper.xml 映射文件
<mapper namespace="user">
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
</mapper>编写删除实体 User 的代码
@org.junit.Test
public void testDelete() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("user.deleteUser",1);
sqlSession.commit();
sqlSession.close();
}删除操作注意的问题
MyBatis 的修改操作
修改语句使用 update 标签
修改操作使用的 API 是 sqlSession.update("命名空间.id", 实体对象)
编写 UserMapper.xml 映射文件
<mapper namespace="user">
<update id="updateUser" parameterType="com.mfc.entity.User">
update user set username=#{username} where id=#{id}
</update>
</mapper>编写修改实体 User 的代码
@org.junit.Test
public void testUpdate() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(3);
user.setUsername("zhangsan");
sqlSession.update("user.updateUser",user);
sqlSession.commit();
sqlSession.close();
}修改操作注意的问题
3.Mybatis 映射文件解释
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- default 指定默认环境的名称 -->
<environments default="dev">
<!-- id指定当前环境名称 -->
<environment id="dev">
<!-- 事务管理类型,交由 JDBC 管理事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 指定当前数据源类型是连接池 -->
<dataSource type="POOLED">
<!-- 数据源配置的基本参数 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
4.核心配置文件分析
MyBatis 核心配置文件层级关系
environments 标签
UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接
POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来
JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用
JDBC:这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的链接来管理事务作用域
MANAGED:此配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为
数据库环境的配置,支持多环境配置
其中,事务管理器(transactionManager)类型有两种
其中,数据源(DataSource)类型有三种:
mapper 标签
使用相对于类路径的资源引用:
<mapper resource="mapper/UserMapper.xml"></mapper>
使用完全限定资源定位符(URL):
<mapper url="file:///var/mappers/UserMapper.xml"/>
使用映射器接口实现类的完全限定类名:
<mapper class="com.mfc.dao.UserDao"/>
将包内的映射器接口实现全部注册为映射器
<package name="com.mfc.dao"/>
该标签的作用是加载映射,加载方式有下面几种
5.Mybatis 常用 API 介绍
SqlSession 工厂构造器 SqlSessionFactoryBuilder
常用 API:sqlSessionFactoryBuilder.build(inputStream);
通过加载 MyBatis 的核心文件的输入流的形式构建一个 SqlSessionFactory 对象
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);其中,Resources 工具类在 org.apache.ibatis.io 包中,Resources 类帮助我们从类路径下、文件系统或一个 web URL 中加载资源文件
SqlSession 工厂对象 SqlSessionFactory
openSession():会默认开启一个事务,但事务不会自动提交,也就意味着需要手动提交事务,更新操作数据才会持久化到数据库中
openSession(boolean autoCommit):参数为是否自动提交事务,如果设置为 true,那么不需要手动提交事务
SqlSessionFactory 有多个方法创建 SqlSession 实例,常用的有两个:
SqlSession 会话对象
SqlSession 实例在 Mybatis 中是非常强大的一个类。在这里可以看到所有执行语句、提交或回滚事务和获取映射器实例的方法。
执行语句的方法主要有:
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)操作事务的方法主要有:
void commit()
void rollback()
6.MyBatis 的 Dao 层实现(传统模式)
编写 UserDao 接口
public interface UserDao {
public List<User> findAll() throws Exception;
}编写 UserDaoImpl 实现
public class UserDaoImpl implements UserDao {
@Override
public List<User> findAll() throws Exception {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("user.selectList");
sqlSession.close();
return users;
}
}测试传统方式
@org.junit.Test
public void testSelect() throws Exception{
UserDao userDao = new UserDaoImpl();
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
7.MyBatis 的 Dao 层实现(代理模式)
采用 MyBatis 的代理开发方式实现 Dao 层的开发,这种方式是现在企业中使用的主流方式
Mapper 接口开发方式只需要程序员编写 Mapper 接口(相当于 Dao 接口),由 Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边的 Dao 接口实现类方法
Mapper 接口开发遵循以下规范
Mapper.xml 文件中的 namespace 与 mapper 接口的全限定名相同
Mapper 接口方法名和 Mapper.xml 中定义的每个 statement 的 id 相同
Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 Sql 的 parameterType 的类型相同
Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 Sql 的 resultType 的类型相同
测试
UserMapper.xml 映射文件编写
<mapper namespace="com.mfc.dao.UserDao">
<select id="findAll" resultType="com.mfc.entity.User">
select * from user
</select>
</mapper>UserDao 接口编写
public interface UserDao {
public List<User> findAll() throws Exception;
}测试类:
@org.junit.Test
public void testSelect() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> all = userDao.findAll();
for (User user : all) {
System.out.println(user);
}
sqlSession.close();
}
三、MyBatis 配置文件深入(面试点)
1.核心配置文件 SqlMapConfig.xml
MyBatis 核心配置文件层级关系
environments 标签
UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接
POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来
JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用
JDBC:这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的链接来管理事务作用域
MANAGED:此配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为
数据库环境的配置,支持多环境配置
其中,事务管理器(transactionManager)类型有两种
其中,数据源(DataSource)类型有三种:
mapper 标签
使用相对于类路径的资源引用:
<mapper resource="mapper/UserMapper.xml"></mapper>
使用完全限定资源定位符(URL):
<mapper url="file:///var/mappers/UserMapper.xml"/>
使用映射器接口实现类的完全限定类名:
<mapper class="com.mfc.dao.UserDao"/>
将包内的映射器接口实现全部注册为映射器
<package name="com.mfc.dao"/>
该标签的作用是加载映射,加载方式有下面几种
properties 标签
实际开发中,习惯将数据源的配置信息单独抽取成一个 properties 文件,该标签可以加载额外配置的 properties 文件
typeAliases 标签
方法一:使用 typeAlias 标签取别名
方法二:使用 package 标签取别名。给实体类所在的包下面的所有实体类取别名,别名就是类名,并且不区分大小写
类型别名是为 Java 类型设置一个短的名字。原来的类型名称如下
配置 typeAliases ,为 com.mfc.entity.User 定义别名为 user
上面是程序员可以自定义的别名,Mybatis 框架已经为我们设置好了一些常用的别名
2.映射配置文件 mapper.xml
动态 SQL:MyBatis 的映射文件中,前面我们使用的 SQL 都比较简单,有些时候业务逻辑复杂时,SQL 会是动态变化的,此时前面那些简单的 SQL 就不能满足要求了
<foreach> 标签的属性含义:
Mapper.xml 编写
<mapper namespace="com.mfc.dao.UserDao">
<select id="findByIds" parameterType="list" resultType="com.mfc.entity.User">
select * from user
<where>
<foreach collection="array" open="id in(" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
</mapper>测试类编写:
@org.junit.Test
public void testFindByIds() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
int[] arr = {1,2,3,4};
List<User> users = sqlSession.selectList("com.mfc.dao.UserDao.findByIds", arr);
for (User user : users) {
System.out.println(user);
}
}collection:代表要遍历的几何元素,注意编写时不要写 #{}
open:代表语句的开始部分
close:代表语句的结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
Mapper.xml 编写
<mapper namespace="com.mfc.dao.UserDao">
<select id="selectList" resultType="com.mfc.entity.User" parameterType="com.mfc.entity.User">
select * from user
<where>
<if test="id != 0">
and id = #{id}
</if>
<if test="username != null">
and username = #{username}
</if>
</where>
</select>
</mapper>测试类编写:
@org.junit.Test
public void test() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(2);
user.setUsername("zahngsan");
List<User> users = sqlSession.selectList("com.mfc.dao.UserDao.selectList",user);
for (User user1 : users) {
System.out.println(user1);
}
sqlSession.close();
}控制台打印SQL:
先在SqlMapConfig.xml 中开启日志打印
运行测试类,查看控制台SQL
动态 SQL 之 <if> 标签:根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如 id 不为空的时候,可以根据 id 查询,username 不为空的时候,可以根据 username 查询。这种情况通常在多条件组合查询中遇到
动态 SQL 之 <foreach> 标签:循环执行 SQL 的拼接操作,如:select * from user where id in (1,2,3)
控制台打印结果
SQL 片段抽取
Sql 中可以将重复的 Sql 提取出来,使用时用 include 引用即可,最终达到 SQL 重用的目的
四、MyBatis 复杂映射开发(面试点)
1.一对一查询
一对一查询模型
用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询一个订单,与此同时查询出该订单的所属用户
一对一查询语句
查看 orders 表数据
查看 user 表数据
编写一对一查询语句并执行:select * from orders o,user u where o.uid=u.id;
MyBatis 实现一对一
编写 Orders 实体类
public class Orders {
private Integer id;
private String ordertime;
private Double total;
private User user;
// set、get、toString 方法省略。。。
}编写 User 实体类
public class User {
private Integer id;
private String username;
// set、get、toString 方法省略。。。
}创建 OrdersDao 接口
public interface OrdersDao {
public List<Orders> selectOrders();
}编写 OrderMapper.xml 映射文件
<mapper namespace="com.mfc.dao.OrdersDao">
<resultMap id="orderMap" type="com.mfc.entity.Orders">
<result property="id" column="id"></result>
<result property="ordertime" column="ordertime"></result>
<result property="total" column="total"></result>
<association property="user" javaType="com.mfc.entity.User">
<id property="id" column="uid"></id>
<result property="username" column="username"></result>
</association>
</resultMap>
<select id="selectOrders" resultMap="orderMap">
select * from orders o,user u where o.uid=u.id
</select>
</mapper>编写测试类
@org.junit.Test
public void test() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
SqlSession sqlSession = factory.openSession();
OrdersDao ordersDao = sqlSession.getMapper(OrdersDao.class);
List<Orders> orders = ordersDao.selectOrders();
for (Orders order : orders) {
System.out.println(order);
}
}测试结果
2.一对多查询
一对多查询模型
用户表和订单表的关系为:一个用户有多个订单,一个订单只从属一个用户
一对多查询需求:查询一个用户,以此同时查询出该用户具有的订单
一对多查询语句
查看 orders 表数据
查看 user 表数据
编写一对多查询语句并执行:select *,o.id oid from user u left join orders o on o.uid=u.id
MyBatis 实现一对多
编写 Orders 实体类
public class Orders {
private Integer id;
private String ordertime;
private Double total;
private Integer uid;
// set、get、toString 方法省略。。。
}编写 User 实体类
public class User {
private Integer id;
private String username;
private List<Orders> orders = new ArrayList<>();
// set、get、toString方法省略。。。
}编写 UserDao 接口
public interface UserDao {
public List<User> selectUser() throws Exception;
}编写 UserMapper.xml 映射文件
<mapper namespace="com.mfc.dao.UserDao">
<resultMap id="userMap" type="com.mfc.entity.User">
<result property="id" column="id"></result>
<result property="username" column="username"></result>
<collection property="orders" ofType="com.mfc.entity.Orders">
<id property="id" column="oid"></id>
<result property="ordertime" column="ordertime"></result>
<result property="total" column="total"></result>
</collection>
</resultMap>
<select id="selectUser" resultMap="userMap">
select *,o.id oid from user u left join orders o on o.uid=u.id
</select>
</mapper>测试类
@org.junit.Test
public void test() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
SqlSession sqlSession = factory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> users = userDao.selectUser();
for (User user : users) {
System.out.println(user);
}
}测试结果
3.多对多查询
多对多查询模型
⽤户表和⻆⾊表的关系为,⼀个⽤户有多个⻆⾊,⼀个⻆⾊被多个⽤户使⽤
多对多查询的需求:查询⽤户同时查询出该⽤户的所有⻆⾊
多对多查询语句
查询语句
执行效果
查看 user 表数据
查看中间表 user_role 数据
查看 role 表数据
编写多对多查询语句并执行
SELECT
u.*, r.id rid,
r.rolename rolename
FROM
USER u
LEFT JOIN user_role ur ON u.id = ur.uid
INNER JOIN role r ON ur.rid = r.idMyBatis 实现多对多
编写 User 实体类
public class User {
private Integer id;
private String username;
private List<Role> roles = new ArrayList<>();
// set、get、toString方法省略。。。
}编写 Role 实体类
public class Role {
private Integer id;
private String rolename;
// set、get、toString方法省略。。。
}编写 UserDao 接口
public interface UserDao {
public List<User> selectUser() throws Exception;
}编写 UserMapper.xml 映射文件
<mapper namespace="com.mfc.dao.UserDao">
<resultMap id="userMap" type="com.mfc.entity.User">
<result property="id" column="id"></result>
<result property="username" column="username"></result>
<collection property="roles" ofType="com.mfc.entity.Role">
<id property="id" column="rid"></id>
<result property="rolename" column="rolename"></result>
</collection>
</resultMap>
<select id="selectUser" resultMap="userMap">
SELECT
u.*, r.id rid,
r.rolename rolename
FROM
USER u
LEFT JOIN user_role ur ON u.id = ur.uid
INNER JOIN role r ON ur.rid = r.id
</select>
</mapper>测试类
@org.junit.Test
public void test() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
SqlSession sqlSession = factory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> users = userDao.selectUser();
for (User user : users) {
System.out.println(user.getUsername());
List<Role> roles = user.getRoles();
for (Role role : roles) {
System.out.println(role);
}
System.out.println("==================");
}
}测试结果
以上是关于基于 XML 的 MyBatis 应用的主要内容,如果未能解决你的问题,请参考以下文章