GVKun编程网logo

MyBatis关系查询(mybatis 关联查询)

14

在本文中,您将会了解到关于MyBatis关系查询的新资讯,同时我们还将为您解释mybatis关联查询的相关在本文中,我们将带你探索MyBatis关系查询的奥秘,分析mybatis关联查询的特点,并给出

在本文中,您将会了解到关于MyBatis关系查询的新资讯,同时我们还将为您解释mybatis 关联查询的相关在本文中,我们将带你探索MyBatis关系查询的奥秘,分析mybatis 关联查询的特点,并给出一些关于java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】、java day56【 Mybatis 延迟加载策略 、 Mybatis 缓存、Mybatis 注解开发 】、java-mybaits-015-mybatis逆向工程最佳实践【基础mybatis-generator、tk.mybatis、mubatis-plus】、mybatis 多表查询之多对多关系查询的实现 - xml 方式的实用技巧。

本文目录一览:

MyBatis关系查询(mybatis 关联查询)

MyBatis关系查询(mybatis 关联查询)

MyBatis关系查询

表关系与类的关联关系:

表关系

一对一 一对多 多对一 多对多

类的关联关系

一对一 一对多 多对一 多对多

Mybatis对一,多的定义

Mybatis通过resultMap来维护关系

对于一、多的定义

代码: JavaBean
xml:association

代码: List
xml: collection

示例:

//一个部门中有多个员工
public class Dept{
    private int deptno;
    private String dname;
    private String loc;
    private List<Emp> emps;
}

mapper配置

   <resultMap id="deptMay" type="dept">
        <id property="deptno" column="deptno"/>
        <result property="dname" column="dname"/>
        <result property="loc" column="loc"/>
	    <collection property="emps" ofType="com.trkj.pojo.Emp">-->
           <id property="empno" column="empno"/>-->
           <result property="ename" column="ename"/>-->
        </collection>-->
    </resultMap>

id,result元素

<id property="a" column="deptno" />
<result property="b" column="dname" />
这是最基本的结果集映射。id 和result 将列映射到属性或简单的数据类型字段(String, int, double, Date等)。
这两者唯一不同的是,在比较对象实例时id 作为结果集的标识属性。这有助于提高总体性能,特别是应用缓存和嵌套结果映射的时候。

collection元素

collection:元素处理“has-many”(有多个)这种类型关系
property:关联的属性名
ofType:集合中的元素类型

select查询:

<select id="queryDeptAndEmployees" resultMap="deptEmployeesMap">
	select d.*, e.* from dept d left join emp e 
	on d.deptno = e.deptno
</select>

//一个员工只属于一个部门
public class Emp {
    private int empno;
    private String ename;
    private String job;
    private BigDecimal sal;
    private BigDecimal comm;
    private Date hiredate;
    private Dept dept;
}

mapper配置

<resultMap id="empMay" type="com.trkj.pojo.Emp">
    <id property="empno" column="empno"/>
    <result property="ename" column="ename"/>
    <result property="job" column="job"/>
    <result property="sal" column="sal" javaType="java.math.BigDecimal"/>
    <result property="comm" column="comm" javaType="java.math.BigDecimal" jdbcType="NUMERIC"/>
    <result property="hiredate" column="hiredate"/>
    <association property="dept"  javaType="com.trkj.pojo.Dept">
        <id column="deptno" property="deptno"/>
        <result column="dname" property="dname"/>
        <result column="loc" property="loc"/>
   </association>-->
</resultMap>

association元素

association:元素处理“has-one”(有一个)这种类型关系
property:属性名
javaType:属性类型

select查询:

<select id="queryEmployeeAndDept" resultMap="empDeptMap" 
	parameterType="int">
	select e.*, d.* from emp e inner join dept d 
	on e.deptno = d.deptno
	where e.empno = #{eid}
</select>

//一个员工只有一个领导
public class Emp {
    private int empno;
    private String ename;
    private String job;
    private Date hiredate;
    private BigDecimal sal;
    private BigDecimal comm;
    private Emp mgr;
}

mapper配置:

<resultMap id="empMay" type="com.trkj.pojo.Emp">
    <id property="empno" column="empno"/>
    <result property="ename" column="ename"/>
    <result property="job" column="job"/>
    <result property="sal" column="sal" />
    <result property="comm" column="comm"/>
    <result property="hiredate" column="hiredate"/>
    <association property="mgr"  javaType="com.trkj.pojo.Emp">
   	 <id property="empno" column="a"/>
    <result property="ename" column="b"/>
    <result property="job" column="c"/>
    <result property="hiredate" column="d"/>
    <result property="sal" column="e" />
    <result property="comm" column="f"/>
   </association>-->
</resultMap>

select 查询:

<select id="queryEmployeeAndMgr" resultMap="empMgrMap"
	parameterType="int">
	select e1.*, 
	e2.empno a, e2.ename b, e2.job c,
	e2.hireDate d, 
	e2.sal e, e2.comm f 
	from emp e1 inner join emp e2 
	on e1.mgr = e2.empno
	where e1.empno = #{eid}
</select>

Cache元素—缓存

MyBatis包含一个强大的、可配置、可定制的查询缓存机制。MyBatis 3 的缓存实现有了许多改进,使它更强大更容易配置。默认的情况,缓存是没有开启,除了会话缓存以外,它可以提高性能,且能解决循环依赖。开启二级缓存,您只需要在sql映射文件中加入简单的一行:

cache作用:

  • 所有映射文件里的select语句的结果都会被缓存。
  • 所有映射文件里的insert、update和delete语句执行都会清空缓存。
  • 缓存使用最近最少使用算法(LRU)来回收。
  • 缓存不会被设定的时间所清空。
  • 每个缓存可以存储1024 个列表或对象的引用(不管查询方法返回的是什么)。
  • 缓存将作为“读/写”缓存,意味着检索的对象不是共享的且可以被调用者安全地修改,而不会被其它调用者或者线程干扰。

cache属性:

<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
创建一个FIFO缓存  让60秒就清空一次,存储512 个对象结果或列表引用,并且返回的结果是只读。

属性说明1

eviction 回收算法:
LRU–最近最少使用:移出最近最长时间内都没有被使用的对象(默认)
FIFO–先进先出:移除最先进入缓存的对象。
SOFT–软引用: 空间内存不足时才进行回收。
WEAK–弱引用:垃圾回收器扫描到时即进行回收。

属性说明2

flushInterval: 设置任何正整数,缓存刷新时间
Size: 缓存大小,默认是1024。
readOnly: 属性可以被设置为true 或false。只读缓存将对所有调用者返回同一个实例。因此这些对象都不能被修改,这可以极大的提高性能。可写的缓存将通过序列化来返回一个缓存对象的拷贝。这会比较慢,但是比较安全。所以默认值是false。

java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】

java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】

第1章 Mybatis 连接池与事务深入

1.1 Mybatis 的连接池技术

1.1.1 Mybatis 连接池的分类

1.1.2 Mybatis 中数据源的配置

1.1.3 Mybatis 中 DataSource 的存取

1.1.4 Mybatis 中连接的获取过程分析

 

1.2 Mybatis 的事务控制

1.2.1 JDBC 中事务的回顾

 

1.2.2 Mybatis 中事务提交方式

1.2.3 Mybatis 自动提交事务的设置

第2章 Mybatis 的动态 SQL 语句

2.1 动态 SQL 之标签 

2.1.1 持久层 Dao 接口

2.1.2 持久层 Dao 映射配置

2.1.3 测试

2.2 动态 SQL 之标签 

2.2.1 持久层 Dao 映射配置

2.3 动态标签之标签 

2.3.1 需求

2.3.1.1 在 QueryVo 中加入一个 List 集合用于封装参数

2.3.2 持久层 Dao 接口

2.3.3 持久层 Dao 映射配置

2.3.3.1 编写测试方法

 2.4 Mybatis 中简化编写的 SQL 片段

2.4.1 定义代码片段

2.4.2 引用代码片段

第3章 Mybatis 多表查询之一对多

3.1 一对一查询(多对一)

3.1.1 方式一

3.1.1.1 定义账户信息的实体类

3.1.1.2 编写 Sql 语句

3.1.1.3 定义 AccountUser 类

3.1.1.4 定义账户的持久层 Dao 接口

3.1.1.5 定义 AccountDao.xml 文件中的查询配置信息

3.1.1.6 创建 AccountTest 测试类

3.1.1.7 小结:

3.1.2 方式二

3.1.2.1 修改 Account 类

在 Account 类中加入 User 类的对象作为 Account 类的一个属性。

3.1.2.2 修改 AccountDao 接口中的方法

3.1.2.3 重新定义 AccountDao.xml 文件

3.1.2.4 在 AccountTest 类中加入测试方法

3.2 一对多查询

3.2.1 编写 SQL 语句

3.2.2 User 类加入 List

3.2.3 用户持久层 Dao 接口中加入查询方法

3.2.4 用户持久层 Dao 映射文件配置

3.2.5 测试方法

第4章 Mybatis 多表查询之多对多

4.1 实现 Role 到 User 多对多

4.1.1 用户与角色的关系模型

4.1.2 业务要求及实现 SQL

4.1.3 编写角色实体类

4.1.4 编写 Role 持久层接口

4.1.5 编写映射文件

4.1.6 编写测试类

4.2 实现 User 到 Role 的多对多

4.2.1 User 到 Role 的多对多

4.2.2 作业:实现 User 到 Role 的一对多查询

 

java day56【 Mybatis 延迟加载策略 、 Mybatis 缓存、Mybatis 注解开发 】

java day56【 Mybatis 延迟加载策略 、 Mybatis 缓存、Mybatis 注解开发 】

第 1 章 Mybatis 延迟加载策略

1.1 何为延迟加载?

1.2 实现需求

1.3 使用 assocation 实现延迟加载

1.3.1 账户的持久层 DAO 接口

1.3.2 账户的持久层映射文件

1.3.3 用户的持久层接口和映射文件

1.3.4 开启 Mybatis 的延迟加载策略

1.3.5 编写测试只查账户信息不查用户信息。

1.4 使用 Collection 实现延迟加载

1.4.1 在 User 实体类中加入 List 属性

1.4.2 编写用户和账户持久层接口的方法

1.4.3 编写用户持久层映射配置

1.4.4 编写账户持久层映射配置

1.4.5 测试只加载用户信息

第 2 章 Mybatis 缓存

2.1 Mybatis 一级缓存

2.1.1 证明一级缓存的存在

2.1.1.1 编写用户持久层 Dao 接口

2.1.1.2 编写用户持久层映射文件

2.1.1.3 编写测试方法

2.1.2 一级缓存的分析

2.1.3 测试一级缓存的清空

 2.2 Mybatis 二级缓存

2.2.1 二级缓存结构图

 2.2.2 二级缓存的开启与关闭

2.2.2.1 第一步:在 SqlMapConfig.xml 文件开启二级缓存

2.2.2.2 第二步:配置相关的 Mapper 映射文件

2.2.2.3 第三步:配置 statement 上面的 useCache 属性

2.2.3 二级缓存测试

2.2.4 二级缓存注意事项

第 3 章 Mybatis 注解开发

3.1 mybatis 的常用注解说明

3.2 使用 Mybatis 注解实现基本 CRUD

3.2.1 编写实体类

3.2.2 使用注解方式开发持久层接口

3.2.3 编写 SqlMapConfig 配置文件

3.2.4 编写测试方法

3.3 使用注解实现复杂关系映射开发

3.3.1 复杂关系映射的注解说明

3.3.2 使用注解实现一对一复杂关系映射及延迟加载

3.3.2.1 添加 User 实体类及 Account 实体类

3.3.2.2 添加账户的持久层接口并使用注解配置

3.3.2.3 添加用户的持久层接口并使用注解配置

3.3.2.4 测试一对一关联及延迟加载

3.3.3 使用注解实现一对多复杂关系映射

3.3.3.2 编写用户的持久层接口并使用注解配置

3.3.3.3 编写账户的持久层接口并使用注解配置

 3.3.3.4 添加测试方法

3.4 mybatis 基于注解的二级缓存

3.4.1 在 SqlMapConfig 中开启二级缓存支持

3.4.2 在持久层接口中使用注解配置二级缓存

 

java-mybaits-015-mybatis逆向工程最佳实践【基础mybatis-generator、tk.mybatis、mubatis-plus】

java-mybaits-015-mybatis逆向工程最佳实践【基础mybatis-generator、tk.mybatis、mubatis-plus】

一、概述

三款框架的功能对比

 

Mybatis-generator

通用Mapper

Mybatis-Plus

代码生成器

支持自动生成Model,Mapper,Mapper XML文件

生成方式不够灵活;

生成代码功能较为简单

支持自动生成Entity,Mapper,Mapper XML文件;

提供通用的Mapper模板,生成方式较灵活;

生成的Model文件包含注释能够很好地与数据库表完成映射

支持自动生成Entity,Mapper,Mapper XML,Service,Controller文件;

提供BaseMapper接口

CRUD操作

代码生成后每个Mapper有固定的CRUD方法;

在每个Mapper上分别扩展

提供通用Mapper接口;方便构造统一service

可以扩展通用接口

提供BaseMapper接口;

可以扩展通用接口

条件构造器

每个实体类自己的Example构造条件【对象方式】

提供通用Example【构建sql】

提供Wrapper进行复杂条件构造

乐观锁

 

支持

支持

主键策略

 

支持

支持

分页

 

 

支持

逻辑删除

 

 

支持

通用枚举

 

 

支持

攻击Sql阻断

 

 

支持

性能分析

 

 

支持

  通用Mapper是对Mybatis-generator的升级改造,解决了使用Mybatis-generator可能需要大量重构的问题,并且在这个基础上加入了一些新的功能。

  Mybatis-Plus可以看作是在另一个方向上对Mybatis的升级改造,不仅能够根据数据库表快速生成pojo实体类,还封装了大量CRUD方法,使用Wrapper解决了复杂条件构造等问题,更是根据开发中常见的问题给出了一系列解决方案。

  在拥有Maven和Spring boot的开发框架下,MBG、通用Mapper和MP都可以快速地完成安装,相比于MBG和通用Mapper仅需要执行插件就可以完成基本的开发工作,MP可能需要更多的开发工作量。

  最佳实践参看代码:https://github.com/bjlhx15/java_base_architecture.git

二、Mybatis-generator

  MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代码生成器。它为所有版本的MyBatis以及版本2.2.0之后的iBATIS版本生成代码。它将根据数据库表生成可用于访问表的文件。

  Mybatis-generator主要完成的工作是依据数据库表创建对应的model、dao、mapping文件,可以通过Maven插件或者mybatis-generator的jar包生成。

  这里介绍Maven插件使用方法:

    1、在pom.xml文件中加入mybatis-generator系列插件;

    2、创建generatorConfig.xml文件,在配置文件中指定数据库连接地址、生成类的存放地址、生成对应表的类名等信息;

    3、执行mybatis-generator插件,即可生成相应文件;

    4、此外,mybatis-generator自动生成了example类用于构造复杂的筛选条件

  Mybatis-generator使用较为简单,生成的DAO类及映射文件中包含基本的CRUD操作。

  需要注意的是,在一次项目中多次执行mybatis-generator,xml文件会追加,会覆盖原本的Model、DAO;可以使用如下方式

    

    1、每次清理要生成的xml

    2、自动生成的写入auto,

    3、个人扩展的使用上图方式

  可以参看上述github代码

三、通用Mapper【tk.mybatis】

官网:https://github.com/abel533/Mapper/wiki

  当数据库字段变化频繁时,使用MBG(mybatis-generator)会带来大量的重构工作,对此,通用Mapper给出的解决办法是:给予开发者一个具备丰富的单表方法并且容易扩展的通用的Mapper。

  通用Mapper是对单表的CRUD操作进行了较为详细的实现,使得开发人员可以随意的按照自己的需求选择通用的方法,同时允许开发人员便捷地对通用Mapper进行扩展。

1. 在pom.xml中添加插件配置

<!-- 命令:mvn mybatis-generator:generate -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.6</version>
                <configuration>
                    <!-- 配置实际调用地址-->
                    <configurationFile>src/main/resources/mybatis_generatorConfig/generatorConfig-base.xml
                    </configurationFile>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.38</version>
                    </dependency>
                    <dependency>
                        <groupId>tk.mybatis</groupId>
                        <artifactId>mapper</artifactId>
                        <version>4.0.0</version>
                    </dependency>
                </dependencies>
            </plugin>
View Code

  可以看到,通用Mapper的代码生成实际上是使用了MGB,因此通用Mapper的代码生成器只是调用了MGB,然后在这个基础上加入了一些元素来方便开发。

2. 配置文件generatorConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC
        "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
    <!--导入属性配置,前面我们写的一个配置文件,你也可以直接使用mybatis的jdbc的配置文件 -->
    <properties resource="jdbc.properties"></properties>
    <!-- 数据库驱动,注意,这里必须要修改成你的数据库的驱动地址 -->
    <!--    如果 pom配置这里可以不写-->
    <!--    <classPathEntry  location=".m2/repository/mysql/mysql-connector-java/5.1.8/mysql-connector-java-5.1.8.jar"/>-->

    <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>
        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
            <property name="caseSensitive" value="true"/>
        </plugin>

        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="${jdbc.driver}"
                        connectionURL="${jdbc.url}"
                        userId="${jdbc.username}" password="${jdbc.password}">
        </jdbcConnection>

<!--        <javaTypeResolver>-->
<!--            <property name="forceBigDecimals" value="false"/>-->
<!--        </javaTypeResolver>-->
        <!-- targetProject:生成PO类的位置 -->
        <javaModelGenerator targetPackage="com.github.bjlhx15.mybatis.springboot.base.model.auto"
                            targetProject="../tk-mybatis-springboot-base1/src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- targetProject:mapper xml 映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="autoxml"
                         targetProject="../tk-mybatis-springboot-base1/src/main/resources/mapper/">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!--targetPackage:mapper接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.github.bjlhx15.mybatis.springboot.base.repository.auto"
                             targetProject="../tk-mybatis-springboot-base1/src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <!-- 指定数据库表 -->
        <table tableName="accountbalance" domainObjectName="AccountBalance">
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>


    </context>
</generatorConfiguration>
View Code

  与MGB原有的配置文件相比,这里只是多了一个插件的配置,这个插件的作用是:配置生成的Mapper接口都会自动继承这个接口,也就是说,使用通用Mapper生成的mapper接口即使看上去空空如也,但已经具备了大量的对数据库的操作方法。此外,通用 Mapper 专用代码生成器生成的 Model 会在原有基础上增加 @Table,@Id,@Column 等注解,方便自动与数据库字段进行映射。

3. 在 pom.xml 这一级目录的命令行窗口执行 mvn mybatis-generator:generate或者直接在执行mvn插件即可。

4. 通用Mapper同样有Example的设计,与MGB不同的是,MDB会对每一个表生成对应的Example类,而通用Mapper提供了一个统一的Example类,这个类和 MBG 生成的相比,需要自己设置属性名,这个类还额外提供了更多的方法。

  通用Mapper可以看作是MGB的改进和扩展,一定程度上解决了使用MGB重构的问题。

  可以参看上述github代码

四、Mybatis-Plus

  官网地址:https://mp.baomidou.com/guide/generator.html

  (以下简称MP)是Mybatis的增强工具(MBG和通用Mapper可看成插件),在Mybatis的基础上增加了很多功能,简化开发,提高效率。

在Spring Boot中的引入:

1. 在maven中添加MP启动器

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.1.2</version>
</dependency>

2. 要使用代码生成器还需要添加模板引擎依赖

参看地址:AutoGenerator的使用参考 https://mybatis.plus/guide/generator.html 。

添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎。

Velocity(默认):

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.1</version>
</dependency>

Freemarker:

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.29</version>
</dependency>

Beetl:

<dependency>
    <groupId>com.ibeetl</groupId>
    <artifactId>beetl</artifactId>
    <version>3.0.11.RELEASE</version>
</dependency>

注意!如果您选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。

AutoGenerator generator = new AutoGenerator();

// set freemarker engine
generator.setTemplateEngine(new FreemarkerTemplateEngine());

// set beetl engine
generator.setTemplateEngine(new BeetlTemplateEngine());

// set custom engine (reference class is your custom engine class)
generator.setTemplateEngine(new CustomTemplateEngine());

// other config
...
View Code

3、代码的自动生成。AutoGenerator是MP的代码生成器,通过调用AutoGenerator,进行相应的模板、策略配置可以快速生成Entity、Mapper、Mapper XML、Service、Controller各个模块的代码。

4. MP将通用的CRUD操作封装进BaseMapper接口,而自动生成的Mapper接口便自动继承了BaseMapper接口。复杂的Sql操作,则可以使用QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper)进行动态Sql拼接。

5、此外,MP还支持分页、逻辑删除、通用枚举、Sql注入等功能,在:https://mp.baomidou.com/guide/generator.html

  还有性能分析插件:https://mp.baomidou.com/guide/performance-analysis-plugin.html

与MBG不同,使用Mybatis-Plus自动生成代码需要编写代码,通过调用AutoAutoGenerator类实现代码生成,从这方面来说不如使用插件方便。但是它丰富的功能以及只是相对复杂的配置还是使它领先于MBG以及通用Mapper。

 

 

 

 

 

 

 

 

双方都

mybatis 多表查询之多对多关系查询的实现 - xml 方式

mybatis 多表查询之多对多关系查询的实现 - xml 方式

  Mybatis 对于多对多关系下的查询提供了集合(collection)的概念来解决,collection 属性是 resultMap 高级结果映射的子集,首先,在本例中我们使用的是集合元素来解决多对多的查询。 然后你会注意到有一个新的 “ofType” 属性。这个属性非常重要,它用来将 JavaBean(或字段)属性的类型和集合存储的类型区分开来。在集合中 ofType 指的是集合中元素的类型。

  首先介绍一下 Demo 情况:

  • 实体类:User(用户)类和 Role(角色)类,类中的属性在后面代码中贴出
  • 关系:一个用户可以有多个角色,一个角色可以赋予多个用户中
  • 数据库表结构:用户表、角色表、中间表(用于存储用户和角色的关系)
  • 本例中实现查询的目标:查询用户时同时获取用户所拥有的角色的信息(当查询角色时同时获取角色所属用户的信息的情况和下面的例子原理一样,主要是修改 select 中的 sql 语句)

  1. 用户实体类以及角色实体类

public class User implements Serializable{
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    private List<Role> roles;

    getset方法省略 ......     
}
public class Role implements Serializable{
    private Integer roleId;
    private String roleName;
    private String roleDesc;
    private List<User> users;
     getset方法省略 ......     
}    

  这里主要是增加用户所拥有的角色的 List 属性和角色所属用户的 List 属性,后面做 resultMap 结果映射的时候使用。

    2. 数据库表结构

DROP TABLE IF EXISTS user;
CREATE TABLE user (
    id INT(11) NOT NULL auto_increment,
    username VARCHAR(32) NOT NULL COMMENT ''用户名称'',
    birthday datetime default NULL COMMENT ''生日'',
    sex char(1) default NULL COMMENT ''性别'',
    address varchar(256) default NULL COMMENT ''地址'',
    PRIMARY KEY (id)
)ENGINE=InnoDB default CHARSET=utf8
INSERT INTO `user` VALUES (''41'', ''老王'', ''2018-02-27 17:47:08'', ''男'', ''石家庄'');
INSERT INTO `user` VALUES (''45'', ''老李'', ''2018-02-27 17:47:08'', ''男'', ''石家庄'');
INSERT INTO `user` VALUES (''46'', ''老郭'', ''2018-02-27 17:47:08'', ''男'', ''石家庄'');
INSERT INTO `user` VALUES (''47'', ''mde'', ''2019-06-26 15:04:25'', ''女'', ''河南'');
INSERT INTO `user` VALUES (''48'', ''nan'', ''2019-08-01 15:04:54'', ''女'', ''合肥'');



DROP TABLE IF EXISTS role;
CREATE TABLE role(
ID int(11) NOT NULL COMMENT ''编号'',
ROLE_NAME VARCHAR(30) DEFAULT NULL COMMENT ''角色名称'',
ROLE_DESC VARCHAR(60) DEFAULT NULL COMMENT  ''角色描述'',
PRIMARY KEY (ID)
)ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO role (ID,ROLE_NAME,ROLE_DESC) VALUES (1,''院长'',''管理整个学院''),(2,''总裁'',''管理整个公司''),(3,''校长'',''管理整个学校'');


DROP TABLE IF EXISTS user_role;
CREATE TABLE user_role(
UID int(11) NOT NULL COMMENT ''用户编号'',
RID INT(11) NOT NULL COMMENT ''角色编号'',
PRIMARY KEY (UID,RID),
CONSTRAINT FK_Reference_10 FOREIGN KEY(RID) REFERENCES role(ID),
CONSTRAINT FK_Reference_9 FOREIGN KEY(UID) REFERENCES user(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO user_role(UID,RID) VALUES(41,1),(45,1),(41,2);

这里主要是增加了中间表。

   3. 在 UserDao 接口中声明查询所有用户的方法 findAll ();

/**
     * 查询所有的用户同时查询出所拥有的角色的信息
     *
     * @return
     */
    List<User> findAll();

  4. 在 UserDao.xml 中配置 findAll () 方法

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.dao.UserDao">
    <resultMap id="userMap" type="com.example.domain.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <collection property="roles" ofType="com.example.domain.Role" resultMap="roleMap"/>
    </resultMap>
    <resultMap id="roleMap" type="com.example.domain.Role">
        <id property="roleId" column="rid"/>
        <result property="roleName" column="ROLE_NAME"/>
        <result property="roleDesc" column="ROLE_DESC"/>
    </resultMap>
    <select id="findAll" resultMap="userMap">
       SELECT u.*,r.ID as rid,r.ROLE_DESC,r.ROLE_NAME FROM user u
         LEFT OUTER JOIN user_role ur on u.id = ur.UID
          LEFT OUTER JOIN role r on ur.RID = r.ID
    </select>
</mapper>

  实现多对多关系查询的主要工作都放在了这里,首先通过 resultMap 声明用户类的结果映射,id 以及 result 等标签就是 User 类中的基本属性,User 类中的角色属性 roles 通过 collection 集合标签来映射到结果集中,<collection property="roles" ofType="com.example.domain.Role" resultMap="roleMap"/>,property 对应 User 类中声明的 roles 属性,ofType 用于标识集合中元素的类型,resultMap 用于引用其他的结果映射来说明集合中元素的属性,在这里为 roleMap。如果 roleMap 不在其他地方使用,也可以直接将角色的属性直接配置在 collection 属性的子集里,如以下形式也可以使用。

<resultMap id="userMap" type="com.example.domain.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <!--<collection property="roles" ofType="com.example.domain.Role" resultMap="roleMap"/>-->
        <collection property="roles" ofType="com.example.domain.Role">
        <!--这里的rid是role表中的id,在select语句中为了防止id字段在两个表中都出现导致的重复,所以给role的字段id 起了别名 注意要与select中的别名保持一致--> <id property="roleId" column="rid"/> <result property="roleName" column="ROLE_NAME"/> <result property="roleDesc" column="ROLE_DESC"/> </collection> </resultMap>

 select 中的 SQL 查询语句解释:

<select id="findAll" resultMap="userMap">
       SELECT u.*,r.ID as rid,r.ROLE_DESC,r.ROLE_NAME FROM user u
         LEFT OUTER JOIN user_role ur on u.id = ur.UID
          LEFT OUTER JOIN role r on ur.RID = r.ID
    </select>

  u.*:查询 USER 表中所有的属性

  r.ID as rid:对于 role 表中的 id 起一个别名 rid

  user u LEFT OUTER JOIN user_role ur on u.id = ur.UID:前面的表左连接后面的表,并且连接条件是 User 表中的 id 与 User_role 表中的 uid 相等

  5. 测试代码

 1 public class UserDaoTest {
 2     private InputStream in;
 3     private SqlSession session;
 4 
 5     private UserDao userDao;
 6     private SqlSessionFactory factory;
 7     @Before
 8     public void init()throws Exception{
 9         //获取配置文件
10         in = Resources.getResourceAsStream("SqlMapConfig.xml");
11         //获取工厂
12         factory = new SqlSessionFactoryBuilder().build(in);
13 
14         session = factory.openSession();
15 
16         userDao = session.getMapper(UserDao.class);
17     }
18     @After
19     public void destory()throws Exception{
20         session.commit();
21         session.close();
22         in.close();
23     }
24     @Test
25     public void findAllTest(){
26         List<User> userList = userDao.findAll();
27         for (User user: userList){
28             System.out.println("每个用户的信息");
29             System.out.println(user);
30             System.out.println(user.getRoles());
31         }
32     }
View Code

6. 测试结果

 

原文出处:https://www.cnblogs.com/hopeofthevillage/p/11410221.html

关于MyBatis关系查询mybatis 关联查询的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】、java day56【 Mybatis 延迟加载策略 、 Mybatis 缓存、Mybatis 注解开发 】、java-mybaits-015-mybatis逆向工程最佳实践【基础mybatis-generator、tk.mybatis、mubatis-plus】、mybatis 多表查询之多对多关系查询的实现 - xml 方式等相关知识的信息别忘了在本站进行查找喔。

本文标签: