写点什么

MyBatis(二、基础进阶)

作者:
  • 2022 年 8 月 14 日
    河南
  • 本文字数:4338 字

    阅读完需:约 14 分钟

1、什么是动态 sql 语句?

​ 动态 sql 语句概述:Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL 是动态变化的, 此时在前面的学习中我们的 SQL 就不能满足要求了。


​ 参考的官方文档,描述如下:



2、动态 sql 语句

1) 动态 SQL 之< if />

​ 我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。


    <select id="findByCondition" parameterType="user" resultType="user">        <include refid="selectUser"></include>        <where>            <if test="id!=0">                and id=#{id}            </if>            <if test="username!=null">                and username=#{username}            </if>            <if test="password!=null">                and passwords=#{passwords}            </if>        </where>    </select>
复制代码


​ 当查询条件 id 和 username 都存在时,控制台打印的 sql 语句如下:



2) 动态 SQL 之< foreach >

​ 循环执行 sql 的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)。


   <select id="findByIds" parameterType="list" resultType="user">        <include refid="selectUser"></include>        <where>            <foreach collection="list" open="id in(" close=")" item="id" separator=",">                #{id}            </foreach>        </where>    </select>
复制代码


​ 控制台打印的 sql 语句如下:



foreach 标签的属性含义如下:


< foreach >标签用于遍历集合,它的属性:


  • collection:代表要遍历的集合元素,注意编写时不要写 #{}

  • open:代表语句的开始部分

  • close:代表结束部分

  • item:代表遍历集合的每个元素,生成的变量名

  • sperator:代表分隔符

3、SQL 片段抽取

​ Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的


  <!--sql语句抽取-->    <sql id="selectUser">select * from user</sql>
<select id="findByCondition" parameterType="user" resultType="user"> <include refid="selectUser"></include> <where> <if test="id!=0"> and id=#{id} </if> <if test="username!=null"> and username=#{username} </if> <if test="password!=null"> and passwords=#{passwords} </if> </where> </select>
<select id="findByIds" parameterType="list" resultType="user"> <include refid="selectUser"></include> <where> <foreach collection="list" open="id in(" close=")" item="id" separator=","> #{id} </foreach> </where> </select>
复制代码

4、MyBatis 映射文件配置:

  • < select > :查询

  • < insert > :插入

  • < update>:修改

  • < delete > :删除

  • < where> :where 条件

  • < if>:if 判断

  • < foreach > :循环

  • < sql > :sql 片段抽取

5、plugins 标签

​ MyBatis 可以使用第三方的插件来对功能进行扩展,分页助手 PageHelper 是将分页的复杂操作进行封装,使用简单的方式即 可获得分页的相关数据 开发步骤:

① 导入通用 PageHelper 的坐标


<!-- 分页助手 --><dependency>    <groupId>com.github.pagehelper</groupId>    <artifactId>pagehelper</artifactId>    <version>3.7.5</version></dependency><dependency>    <groupId>com.github.jsqlparser</groupId>    <artifactId>jsqlparser</artifactId>    <version>0.9.1</version></dependency>
复制代码


② 在 mybatis 核心配置文件中配置 PageHelper 插件


<!-- 注意:分页助手的插件 配置在通用馆mapper之前 --><plugin interceptor="com.github.pagehelper.PageHelper">    <!-- 指定方言 -->    <property name="dialect" value="mysql"/></plugin>
复制代码


③ 测试分页数据获取


@Testpublic void testPageHelper(){  //设置分页参数  PageHelper.startPage(1,2);  List<User> select = userMapper2.select(null);  for(User user : select){    System.out.println(user);  }}
复制代码


获得分页相关的其他参数


PageInfo<User> pageInfo = new PageInfo<User>(select);System.out.println("总条数:"+pageInfo.getTotal());System.out.println("总页数:"+pageInfo.getPages());System.out.println("当前页:"+pageInfo.getPageNum());System.out.println("每页显示长度:"+pageInfo.getPageSize());System.out.println("是否第一页:"+pageInfo.isIsFirstPage());System.out.println("是否最后一页:"+pageInfo.isIsLastPage());
复制代码


6、Mybatis 多表查询

一对一查询

​ 用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户 一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户。



​ 对应的 sql 语句:


select * from orders o,user u where o.uid=u.id;
复制代码


​ 创建 Order 和 User 实体:


public class User {  private int id;  private String username;  private String password;  private Date birthday;}
复制代码


public class Order {  private int id;  private Date ordertime;  private double total;  //代表当前订单从属于哪一个客户  private User user;}
复制代码


​ 创建 OrderMapper 接口:


public interface OrderMapper {  List<Order> findAll();}
复制代码


​ 配置 OrderMapper.xml:


<mapper namespace="com.xmp.mapper.OrderMapper">  <resultMap id="orderMap" type="com.xmp.domain.Order">    <result column="uid" property="user.id"></result>    <result column="username" property="user.username"></result>    <result column="passwords" property="user.passwords"></result>    <result column="birthday" property="user.birthday"></result>  </resultMap>  <select id="findAll" resultMap="orderMap">    select * from orders o,user u where o.uid=u.id  </select></mapper>
复制代码


​ Test


OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);  List<Order> all = mapper.findAll();  for(Order order : all){    System.out.println(order);  }
复制代码

一对多查询

​ 用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户 一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单。



​ 对应的 sql 语句:


select *,o.id oid from user u left join orders o on u.id=o.uid;
复制代码


​ 修改 User 实体:


public class User {  private int id;  private String username;  private String password;  private Date birthday;  //代表当前用户具备哪些订单  private List<Order> orderList;}
复制代码


​ 创建 UserMapper 接口:


public interface UserMapper {  List<User> findAll();}
复制代码


​ 配置 UserMapper.xml:


<mapper namespace="com.xmp.mapper.UserMapper">  <resultMap id="userMap" type="com.xmp.domain.User">    <result column="id" property="id"></result>    <result column="username" property="username"></result>    <result column="password" property="password"></result>    <result column="birthday" property="birthday"></result>      <collection property="orderList" ofType="com.xmp.domain.Order">        <result column="oid" property="id"></result>        <result column="ordertime" property="ordertime"></result>        <result column="total" property="total"></result>      </collection>  </resultMap>  <select id="findAll" resultMap="userMap">    select *,o.id oid from user u left join orders o on u.id=o.uid  </select></mapper>
复制代码


​ Test:


UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> all = mapper.findAll();  for(User user : all){    System.out.println(user.getUsername());    List<Order> orderList = user.getOrderList();    for(Order order : orderList){      System.out.println(order);    }}
复制代码

多对多查询

​ 用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用 多对多查询的需求:查询用户同时查询出该用户的所有角色。



​ 对应的 sql 语句:


select u.*,r.*,r.id rid from user u left join user_role ur on u.id=ur.user_id inner join role r on ur.role_id=r.id;
复制代码


​ 创建 Role 实体,修改 User 实体


public class User {  private int id;  private String username;  private String password;  private Date birthday;  //代表当前用户具备哪些订单  private List<Order> orderList;  //代表当前用户具备哪些角色  private List<Role> roleList;}
复制代码


public class Role {  private int id;  private String rolename;}
复制代码


​ 添加 UserMapper 接口方法


List<User> findAllUserAndRole();
复制代码


​ 配置 UserMapper.xml


<resultMap id="userRoleMap" type="com.itheima.domain.User">  <result column="id" property="id"></result>  <result column="username" property="username"></result>  <result column="password" property="password"></result>  <result column="birthday" property="birthday"></result>    <collection property="roleList" ofType="com.itheima.domain.Role">      <result column="rid" property="id"></result>      <result column="rolename" property="rolename"></result>    </collection></resultMap><select id="findAllUserAndRole" resultMap="userRoleMap">  select u.*,r.*,r.id rid from user u left join user_role ur on   u.id=ur.user_id  inner join role r on ur.role_id=r.id</select>
复制代码


​ Test:


UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> all = mapper.findAllUserAndRole();for(User user : all){  System.out.println(user.getUsername());  List<Role> roleList = user.getRoleList();  for(Role role : roleList){    System.out.println(role);  }}
复制代码


MyBatis 多表配置方式:


  • 一对一配置:使用< resultMap >做做配置

  • 一对多配置:使用< resultMap >+< collection >做配置

  • 多对多配置:使用< resultMap >+< collection > 做配置

发布于: 3 小时前阅读数: 19
用户头像

关注

在校大三学生一枚 2022.08.02 加入

喜欢学习编程,擅长技术栈JAVA

评论

发布
暂无评论
MyBatis(二、基础进阶)_mybatis_斯_InfoQ写作社区