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>
复制代码
③ 测试分页数据获取
@Test
public 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 > 做配置
评论