1、什么是动态sql语句?
动态sql语句概述:Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的, 此时在前面的学习中我们的 SQL 就不能满足要求了。
参考的官方文档,描述如下:
2、动态sql语句
1) 动态 SQL 之< if />
我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
<selectid="findByCondition"parameterType="user"resultType="user"><includerefid="selectUser"></include><where><iftest="id!=0">andid=#{id} </if><iftest="username!=null">andusername=#{username} </if><iftest="password!=null">andpasswords=#{passwords} </if></where></select>
当查询条件id和username都存在时,控制台打印的sql语句如下:
2) 动态 SQL 之< foreach >
循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)。
<selectid="findByIds"parameterType="list"resultType="user"><includerefid="selectUser"></include><where><foreachcollection="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>
③ 测试分页数据获取
publicvoidtestPageHelper(){ //设置分页参数PageHelper.startPage(1,2); List<User>select=userMapper2.select(null); for(Useruser : 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*fromorderso,useruwhereo.uid=u.id;
创建Order和User实体:
publicclassUser { privateintid; privateStringusername; privateStringpassword; privateDatebirthday; } publicclassOrder { privateintid; privateDateordertime; privatedoubletotal; //代表当前订单从属于哪一个客户privateUseruser; } 创建OrderMapper接口:publicinterfaceOrderMapper { 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
OrderMappermapper=sqlSession.getMapper(OrderMapper.class); List<Order>all=mapper.findAll(); for(Orderorder : all){ System.out.println(order); }
一对多查询
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户 一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单。
对应的sql语句:
select*,o.idoidfromuseruleftjoinordersoonu.id=o.uid;
修改User实体:
publicclassUser { privateintid; privateStringusername; privateStringpassword; privateDatebirthday; //代表当前用户具备哪些订单privateList<Order>orderList; }
创建UserMapper接口:
publicinterfaceUserMapper { 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:
UserMappermapper=sqlSession.getMapper(UserMapper.class); List<User>all=mapper.findAll(); for(Useruser : all){ System.out.println(user.getUsername()); List<Order>orderList=user.getOrderList(); for(Orderorder : orderList){ System.out.println(order); } }
多对多查询
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用 多对多查询的需求:查询用户同时查询出该用户的所有角色。
对应的sql语句:
selectu.*,r.*,r.idridfromuseruleftjoinuser_roleuronu.id=ur.user_idinnerjoinroleronur.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:
UserMappermapper=sqlSession.getMapper(UserMapper.class); List<User>all=mapper.findAllUserAndRole(); for(Useruser : all){ System.out.println(user.getUsername()); List<Role>roleList=user.getRoleList(); for(Rolerole : roleList){ System.out.println(role); } }
MyBatis多表配置方式:
- 一对一配置:使用< resultMap >做做配置
- 一对多配置:使用< resultMap >+< collection >做配置
- 多对多配置:使用< resultMap >+< collection > 做配置