动态sql,关联查询

1、动态sql

1.2.1 sql标签

可以通过sql标签提高sql代码的复用性

定义代码片段

<sql id="sql_count">select count(*)</sql>

使用代码片段

<select id="selectUserCount" resultType="String">
	<include refid="sql_count"/> from t_user
</select>

1.2.2 if标签

进行条件判断,判断成功会把if内部SQL拼接到外部SQL中,否则不拼接

<if test="条件">
	SQL语句
</if>

问题:直接使用if会出现多余的where和and、or等关键词

1.2.3 where标签

用于配置条件,会去掉多余的where、and、or关键词

select * from xx
<where>
    <if test="条件">
    	SQL语句
    </if>
</where>

1.2.4 set标签

用于配置update语句,用于去掉多余的,

update xx 
<set>
    <if test="条件">
    列 = 值,
    </if>
    <if test="条件">
    列 = 值,
    </if>
	...
</set>
where 条件

1.2.5 trim标签

可以删除或添加前缀和后缀,用来拼接SQL

<trim prefix="添加前缀" suffix="添加后缀" prefixOverride="删除后缀" suffixOverride="删除后缀">
	<if>...</if>
</trim>

用trim代替set

<trim prefix="set" suffixOverride=",">
	..
</trim>

1.2.6 foreach标签

用于循环拼接SQL

<foreach collection="集合参数名称" item="变量名" open="开始符号" close="结束符号" seprator="分割符" index="下标">
	#{变量名}
</foreach> 

List<Employee> selectByIds(List<Long> ids);
--->
select * from employee where id in (1,2,3,4)

<select id="selectByIds" resultType="Employee">
    <include refid="mySelect"></include>
    where emp_id in
    <foreach collection="ids" item="id" separator="," open="(" close=")" index="i">
    	#{id}
    </foreach>
</select>

2、关联查询

2.1 关联关系的分类

表之间有几种关联关系:

  1. 一对一 如:一个人有一个身份证
  2. 一对多 如:一个部门有多个员工
  3. 多对一 如:多个员工属于一个部门
  4. 多对多 如:一个学生可以选择多门课程,一门课程也有多个学生

2.2 MyBatis实现关联

在进行数据库查询时,会遇到多张表相互关联的情况,下面以书籍和类型为例,配置最常见的一对多关系。

2.3 关联配置

MyBatis映射文件中,在ResultMap里可以配置关联关系

主要有两种标签来映射关联属性:

  • collection 配置集合类型的属性

  • association 配置单独对象的属性

collection和association的相关参数:

  • property 属性的名称
  • select 查询方法
  • javaType 属性的类型
  • ofType 如果属性是集合,集合中对象的类型
  • column 外键字段名

2.3.1 查询集合

配置一的一方,查询书籍类型时,能同时查询到该类型的所有书籍

1) 给类型添加书籍集合,这里需要使用collection

public class BookType {

  private long id;
  private String type;
  //书籍的集合
  private List<Book> books;
  ..
 }

2) 书籍类型Mapper接口

public interface IBookTypeDAO {

    /**
     * 按id查书籍类型
     * @param typeId
     * @return
     */
    BookType selectBookTypeById(int typeId);
}

3) 在Book映射接口中定义方法

    /**
     * 根据类型id查询所有书籍
     * @param typeId
     * @return
     */
    List<Book> selectBooksByTypeId(int typeId);

4) BookType的映射文件

<resultMap id="bookTypeMap" type="BookType" >
    <id property="id" column="id"></id>
    <result property="type" column="type"></result>
    <!--配置集合 property是集合属性 select是查询方法 javaType是集合类型
    ofType是集合的数据类型 column外建列作为参数传入查询方法-->
    <collection property="books" select="com.blb.bookms.dao.IBookDAO.selectBooksByTypeId"
              javaType="java.util.List"   ofType="Book" column="id">
    </collection>
</resultMap>

<select id="selectBookTypeById" resultMap="bookTypeMap" parameterType="java.lang.Integer">
        select * from tb_book_type where id = #{typeId}
</select>

这里使用的是子查询的机制,在查询书籍类型后,将每个类型id作为参数,调用书籍接口的selectBooksByTypeId方法查询书籍集合。

连接查询方式

<resultMap id="deptMap" type="Department">
    <id property="deptId" column="dept_id"></id>
    <result property="deptName" column="dept_name"></result>
    <!--
     员工集合的配置 property属性名 column子查询使用的字段
     javaType集合类型 ofType集合的对象类型
     select是子查询的方法
     -->
        <collection property="employees"
                    javaType="java.util.List" ofType="Employee">
            <id property="empId" column="emp_id"></id>
            <result property="empNo" column="emp_no"></result>
            <result property="empName" column="emp_name"></result>
            <result property="empAge" column="emp_age"></result>
            <result property="empGender" column="emp_gender"></result>
            <result property="empInfo" column="emp_info"></result>
            <result property="empAddress" column="emp_address"></result>
            <result property="empDeptId" column="emp_dept_id"></result>
        </collection>
</resultMap>

<sql id="deptSelect">
    select d.*,e.* from department d join employee e on d.dept_id = e.emp_dept_id
</sql>

<select id="selectAll" resultMap="deptMap">
    <include refid="deptSelect"></include>
</select>

2.3.2 查询单个对象

配置多的一方,通过书籍查询到它所属的类型

  1. 给Book添加BookType属性

    /**

    • 书籍
      */
      public class Book {

      ...

      /书籍类型
      private BookType bookType;

2)书籍映射文件中,使用association配置bookType属性

<resultMap id="bookMap" type="Book">
    <id property="id" column="id"></id>
    <result property="bookName" column="book_name"></result>
    <result property="price" column="price"></result>
    <result property="typeId" column="type_id"></result>
    <result property="author" column="author"></result>
    <result property="publishOrg" column="publish_org"></result>
    <result property="publishTime" column="publish_time"></result>
    <result property="state" column="state"></result>
    <result property="bookImage" column="book_image"></result>
    <!--映射一对一 类型-->
    <association property="bookType" javaType="BookType"
                 select="com.blb.bookms.dao.IBookTypeDAO.selectBookTypeById" column="type_id">
    </association>
</resultMap>

<select id="selectBookById" parameterType="java.lang.Integer" resultMap="bookMap">
    select * from tb_book where id = #{id}
</select>

连接查询

    <resultMap id="empMap" type="Employee" autoMapping="true">
<!--        <id property="empId" column="emp_id"></id>-->
<!--        <result property="empNo" column="emp_no"></result>-->
<!--        <result property="empName" column="emp_name"></result>-->
<!--        <result property="empAge" column="emp_age"></result>-->
<!--        <result property="empGender" column="emp_gender"></result>-->
<!--        <result property="empInfo" column="emp_info"></result>-->
<!--        <result property="empAddress" column="emp_address"></result>-->
<!--        <result property="empDeptId" column="emp_dept_id"></result>-->
        <!--单独对象映射-->
        <association property="department" javaType="Department" autoMapping="true">
<!--            <id property="deptId" column="dept_id"></id>-->
<!--            <result property="deptName" column="dept_name"></result>-->
        </association>
    </resultMap>

    <!--sql语句重用-->
    <sql id="mySelect">
        -- select * from employee
        select d.*,e.* from department d join employee e on d.dept_id = e.emp_dept_id
    </sql>
相关推荐
天天扭码12 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶12 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺17 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
小曲程序24 分钟前
vue3 封装request请求
java·前端·typescript·vue
陈王卜42 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、42 分钟前
Spring Boot 注解
java·spring boot
java亮小白19971 小时前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF1 小时前
java Queue 详解
java·队列
武子康1 小时前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql