一、 动态SQL
概念:
mybatis核心对sql语句进行灵活操作,通过表达式进行判断,
对sql进行灵活拼接、组装。
多条件的查询,需要使用SQL的拼接
String sql="select * from book where 1=1";
if(条件){
sql+=" and 条件";
}
存在问题:
- SQL中出现1=1条件可读性比较低
- 拼接容易出错
- 在DAO层出现大量if语句,代码比较乱
动态SQL的标签
<if> 进行条件判断
<where> sql条件配置
<set> update语句的配置
<trim> 添加和删除前缀和后缀文字
<foreach> 循环
<if>标签
语法:
SQL语句 <if test="条件">SQL语句</if>
判断条件成立后,会将if内部的SQL语句和外部的SQL语句拼接起来
<select id="selectByBook" parameterType="com.hp.mybatis.bean.Book">
select * from book where
<if test="bookName!=null and b_name!=''">
b_name=#{b_name}
</if>
</select>
补充:MyBatis配置文件中配置启动日志
<settings>
<!--配置启动日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
问题:会出现多余的where和and
<where>标签
作用是去掉多余的where、and、or
语法:
SQL语句:<where>
<if></if>
</where>
<set>标签
作用是配置update语句中的set部分,帮助去掉多余的逗号
举个例子:
<update id="updateBook"parameterType="com.hp.bean.Book">
update book
<set>
<if test="b_name!=null and b_name != ''">
b_name=#{b_name},
</if>
<if test="b_author!=null and b_author != ''">
b_author=#{b_author},
</if>
<if test="b_price > 0">
and b_price=#{b_price};
</if>
<if test="b_image!=null and b_image != ''">
b_image=#{b_image},
</if>
<if test="b_publish_date!=null and b_publish_date != ''">
b_publish_date=#{b_publish_date},
</if>
</set>
where b_id=#{b_id}
</update>
<trim>标签
作用是:添加和删除前缀和后缀
语法:
<trim prefix="添加的前缀" suffix="添加的后缀" prefixOverrides="删除的前缀" suffixOverrides="删除的后缀">
</trim>
<foreach>标签
作用是用于循环拼接SQL
查询多个作者的书:
select * from tb_book where book_author in ('张三','李四','王五')
语法:
<foreach collection="集合参数名" item="变量名" open="开始符号" close="结束符号" separator="分隔符" index="下标">
#{变量名}
</foreach>
<select id="selectByAuthorNames" parameterType="java.util.List"
resultMap="bookMap">
select * from tb_book
<where>
book_author in
<foreach collection="authorNames" item="name"
open="(" close=")" separator=",">
#{name}
</foreach>
</where>
</select>
注意:集合参数需要使用@Param注解配置名称
二、关联查询
关系型数据库中表和表之间存在关系的
关系有三种:
- 一对一 (用户和身份证)
- 一对多 (一个人对应多门成绩)
- 多对多 (学生和课程,老师和学生)
实现对象和对象之间关系(书籍和订单)
书籍对象包含多个订单(订单集合)
订单对象包含一个书籍对象
配置方法:
1)子查询
查询两次:
1)通过书籍id查询书籍
2)通过书籍id查询订单
2)关联查询
查询一次,通过连接查询将书籍和订单一起查询
子查询配置:
1)在书籍类中定义订单集合属性,在订单类中定义书籍属性
2)添加OrderMapper接口,定义根据书籍id查询订单的方法
/**
* 订单映射接口
*/
public interface OrderMapper {
/**
* 根据书籍id查订单
* @param bookId
* @return
*/
List<TbOrder> selectOrdersByBookId(
@Param("bookId")long bookId);
}
<?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">
<!--配置接口的映射,namespace命名空间设置为包名+接口名-->
<mapper namespace="com.hopu.mybatis.dao.OrderMapper">
<!--配置结果映射 id是名称,type是实体类类名-->
<resultMap id="orderMap" type="com.hopu.mybatis.entity.TbOrder">
<!--配置主键,property是对象属性名,column表的列名,javatype是属性类型,jdbcType是列类型-->
<id property="orderId" column="order_id" javaType="java.lang.Long" />
<!--配置非主键列-->
<result property="orderBookId" column="order_book_id"/>
<result property="orderTime" column="order_time"/>
<result property="orderNum" column="order_num"/>
<result property="orderCustomerId" column="order_customer_id"/>
</resultMap>
<select id="selectOrdersByBookId" resultMap="orderMap"
parameterType="java.lang.Long">
select * from tb_order where order_book_id = #{bookId}
</select>
</mapper>
3 ) 在书籍的映射文件中,在ResultMap中添加标签:
<collection>标签 配置一对多关系
<!--配置订单集合 property是集合属性名 ofType配置集合中对象的类型
javaType配置集合的类型 select配置实现集合查询的方法 column是用于查询的集合的列-->
<collection property="bookOrders"
ofType="com.hopu.mybatis.entity.TbOrder"
javaType="java.util.ArrayList"
select="com.hopu.mybatis.dao.OrderMapper.selectOrdersByBookId"
column="book_id"/>
4 ) 实现订单类中书籍属性的配置
```java
```java
<association>标签 配置一对一关系
<!--配置书籍对象一对一-->
<association property="orderBook"
javaType="com.hopu.mybatis.entity.TbBook"
select="com.hopu.mybatis.dao.BookMapper.selectById"
column="order_book_id"/>
关联查询:
1)将所有的查询都改为关联查询
select * from tb_book b join tb_order o
on b.book_id = o.order_book_id where book_id=#{bookId}
2)修改collection或association标签
<collection property="bookOrders"
ofType="com.hopu.mybatis.entity.TbOrder"
javaType="java.util.ArrayList"
column="book_id">
<!--配置订单的映射-->
<id property="orderId" column="order_id" javaType="java.lang.Long" />
<!--配置非主键列-->
<result property="orderBookId" column="order_book_id"/>
<result property="orderTime" column="order_time"/>
<result property="orderNum" column="order_num"/>
<result property="orderCustomerId" column="order_customer_id"/>
</collection>
对比子查询和关联查询方式:
1)子查询执行两次,关联查询执行一次
2)子查询不需要修改查询语句,关联查询需要将所有查询语句改为关联查询
3)子查询支持延迟加载,关联查询不支持
延迟加载
也叫懒加载,按需加载,是MyBatis中的一种优化机制
当对象调用对应属性时,才执行属性的查询语句
在子查询可以使用,关联查询无法使用
默认情况下延迟加载是关闭的
配置方法:
<!--启动延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--关闭积极加载-->
<setting name="aggressiveLazyLoading" value="false"/>