mybatis进阶、动态sql和分页查询
1.XML中if标签:
if:使用test属性来判断一个表达式是否成立,只有成立的情况下,才会执行if标签中的sql
2.where标签:优化格式
1)假设where标签中所有的条件都不成立,where标签就相当于没有
2)假设where标签中的条件至少有一个成立
where标签会在代码块最前边添加一个where关键字
还会去除where代码块中得到的第一个and|or关键字
<select id="findByUser1" resultType="com.itheima.domain.User">
select * from user
<where>
<if test="name != null and name !=''">
and name = #{name}
</if>
<if test="email != null and email !=''">
and email = #{email}
</if>
</where>
</select>
3.choose:包含一组条件,这组条件是互斥的(只能有一个成立)===>if else-else
when:相当于java中的if和else if
ohterwise:相当于java中else
查询findByUser2(User user) 根据user对象(name email)中第一个不为空的属性进行查询
如果name不为空 仅仅按照name查询
如果name为空email不为空 仅仅按照email查询
如果都为空 查询不到任何信息
<select id="findByUser2" resultType="com.itheima.domain.User">
select * from user
<where>
<choose>
<when test="name !=null and name !=''">
and name = #{name}
</when>
<when test="email !=null and email !=''">
and email = #{email}
</when>
<otherwise>
and 1=2
</otherwise>
</choose>
</where>
</select>
4.set标签:
不用set的话,不需要更新的属性,会默认更新为null
所以更新要用
注:一个字段都不更新,sql语句不完整,报错
<!--
根据uid进行更新一个user对象中不为空的属性
set作用
1.他可以在你的set代码块前面加上一个set关键字
2.他可以删除你的set代码块的最后一个,
3.set代码块中要求至少有一个条件成立
注意:非字符串类型的数据只需要根据null判断就可以了
-->
<update id="update">
update user
<set>
<if test="name !=null and name !=''">
name = #{name},
</if>
<if test="password !=null and password !=''">
password = #{password},
</if>
<if test="email !=null and email !=''">
email = #{email},
</if>
<if test="birthday !=null">
birthday = #{birthday},
</if>
</set>
where uid = #{uid}
</update>
5.foreach标签
根据uids( 多个uid )查询一个对象的集合
<!--
foreach标签的属性
collection:指定要遍历的数据:值根据传入的参数类型不同产生变化的
a.集合:collection
b.数组:array
c.对象中属性:对象中属性的名称
item:对象中元素,起的临时遍历名称
separator:分隔符
open:开始符
close:结束符
-->
<select id="findByUids1" resultType="com.itheima.domain.User">
select * from user where uid in
<foreach collection="collection"
item="it" separator="," open="(" close=")">
#{it}
</foreach>
</select>
6.xml和注解可以混用嘛
可以,虽然可以同时解析注解和xml但是,但是不能同时对同一个方法既注解又XML配置,不然会报错。
(3条消息) 【紧急避坑】mybatis可以同时使用XML和注解_liangcheng0523的博客-CSDN博客_mybatis注解和xml怎么同时配置
7.编程风格
- 模块 小写 使用-分割
- 类名 首字母大写 驼峰命名
- 方法名 首字母小写 驼峰命名
- com.公司名.[项目名].包名
8.datagrip运行快捷键:ctrl+enter
9.为啥要把数据存到req不存到resp中?
因为resp不是域对象,req是域对象,在转发中不同的servlet可以实现数据共享。
req.getRequestDispatcher("/form.html").forward(req,resp);
注意:req对象的生命周期就是一次请求,再次服务器请求会重新创建。
转发也是一次服务器请求。
10.请求转发和重定向的区别。
1)转发一次服务器请求,重定向两次服务器请求
2)转发服务器内部行为,重定向外部行为,导致url会发生改变。
3)登录失败转发回去,登录成功重定向到首页。
11.拦截器和动态代理的联系?
动态代理是拦截器实现的一种方式。
Java三大器之拦截器(Interceptor)的实现原理及代码示例_reggergdsg的博客-CSDN博客_拦截器
12.拦截器和过滤器的区别?
1)实现原理不同
过滤器和拦截器 底层实现方式大不相同,过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。
2)使用范围不同
过滤器只能在web中
过滤器 实现的是 javax.servlet.Filter
接口,而这个接口是在Servlet
规范中定义的,也就是说过滤器Filter
的使用要依赖于Tomcat
等容器,导致它只能在web
程序中使用。
拦截器就比较广泛。
3)触发时机不同
过滤器 和 拦截器的触发时机也不同,我们看下边这张图。
过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。
拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。
4)拦截的请求范围不同
过滤器几乎可以对所有进入容器的请求起作用,
而拦截器只会对Controller
中请求或访问static
目录下的资源请求起作用。
5)注入Bean情况不同
6)控制执行顺序不同
链接:https://juejin.cn/post/6844904179958284301
13.pageHelper的使用和原理
1)注意事项
要在分页查询逻辑前添加一行代码
PageHelper.startPage(1,10);
2)工作原理
1.使用PageHelper.startPage时在当前线程上下文中设置一ThreadLocal变量
2.在ThreadLocal中设置了分页参数,之后在查询执行的时候,获取当前线程中的分页参数
3.执行查询的时候通过拦截器在sql语句中添加分页参数,之后实现分页查询,查询结束后在 finally 语句中清除ThreadLocal中的查询参数
PageHelper方法使用了静态的ThreadLocal参数,分页参数和线程是绑定的。只要可以保证在PageHelper方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为PageHelper在finally代码段中自动清除了ThreadLocal存储的对象。
下面这样的代码,就是不安全的用法:
PageHelper.startPage(1,10);
Listlist;
if(param1!=null){
list=countryMapper.selectIf(param1);
} else {
// 如果程序走到这个逻辑分支,程序中当前的分页参数无法清除
list=newArrayList();
}
//应该为:
List list;
if(param1!=null) {
PageHelper.startPage(1,10);
list=countryMapper.selectIf(param1);
} else {
list=newArrayList();
}
https://blog.csdn.net/YUAN_YONG_/article/details/107706484
总结:PageHelper首先将前端传递的参数保存到page这个对象中,接着将page的副本存放入ThreadLoacl中,这样可以保证分页的时候,参数互不影响,接着利用了mybatis提供的拦截器,取得ThreadLocal的值,重新拼装分页SQL,完成分页。