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 >标签用于遍历集合,它的属性:
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 > 做配置
评论