MyBatis复杂查询【MyBatis笔记四】

目录

1.in 查询

2.like 模糊查询

3.between and 区间查询

4.分⻚

方式一:RowBounds 逻辑分页

方式二:pageHelper分页插件 物理分页

优缺点

5.resultMap  处理列名不一致问题(多表查询)


1.in 查询

(StudentMapper2.xml) 中添加 foreach 标签
<select id="finda" resultType="student">
   select * from student where studentid in
   <foreach collection="list" item="sid" open="(" close=")" separator=",">
       #{sid}
   </foreach>  <!-- 相当于 select * from student where studentid in (1,3,5,7) -->
</select>

foreach 标签中属性说明:

item 表示集合中每⼀个元素进⾏迭代时的别名,等同于c 标签中的var

index 指定⼀个名字,⽤于表示在迭代过程中,每次迭代到的位置,可以不写

open 表示该语句以什么开始,

separator 表示在每次进⾏迭代之间以什么符号作为分隔符,

close 表示以什么结束,

collection 表示类型(list 时取值 list ,数组时取值 array,map 时取值 map 的 key 值) 该属性是必须指定的

注意:在使⽤ foreach 的时候最关键的也是最容易出错的就是 collection 属性

 

(1)参数是 list 类型 collection="list"

(StudentMapper.xml)
<select id="finda" resultType="student">
   select * from student where studentid in
   <foreach collection="list" item="sid" open="(" close=")" separator=",">
       #{sid}
   </foreach>
</select>
注意:parameterType 的值可以省略
(TestIn.java)
public class TestIn {
    public static void main(String[] args) {
        //多线程 threadLocal 优化的 session 对象
        SqlSession session = SqlSessionUtil.getSession();
        //省略实现类  使用反射得到接口
        StudentDao2 studentDao2 = session.getMapper(StudentDao2.class);
        List list=new ArrayList();
        list.add(1);
        list.add(3);
        list.add(5);
        list.add(7);
        List<Student> students = studentDao2.finda(list);
        for (Student student : students) {
            System.out.println(student);
        }
        SqlSessionUtil.closeSession();
    }
}

 

(2)参数是数组类型 collection="array"

<select id="findb" resultType="student">
    select * from student where studentid in
    <foreach collection="array" item="sid" open="(" close=")" separator=",">
        #{sid}
    </foreach>
</select>
注意:parameterType 的值可以省略
int[] ids=new int[]{1,3,5,7};
List<Student> students = studentDao2.findb(ids);

 

(3)参数是 Map 类型  collection="map 时取值 map 的 key 值"

<select id="findc" resultType="student">
    select * from student where studentid in
    <foreach collection="ids" item="sid" open="(" close=")" separator=",">
         #{sid}
    </foreach>
</select>
注意:parameterType 的值可以省略
Map map=new HashMap();
List list=new ArrayList();
list.add(1);
list.add(3);
list.add(5);
list.add(7);
map.put("ids",list);
List<Student> students = studentDao2.findc(map);

 

2.like 模糊查询

<if test="ename!=null and ename!=''">
   and ename like '%${属性名}%'
</if>
或者:
<if test="ename!=null and ename!=''">
   and ename like "%"#{username}"%"
</if>

注意:test属性中读取属性值时直接写属性名

#{}:相当于占位符

#{id}:其中的id可以表示输⼊参数的名称,如果是简单类型名称可以任意

${}:表示拼接sql语句

${value}:表示获取输⼊的参数值,${}会引起SQL注⼊,⼀般情况下不推荐使⽤。


!!!如果传递过来的是map类型,则test属性中写的是key
<select id="findd" resultType="student">
    select * from student where 1=1
    <if test="stuname!=null and stuname !=''">
        and  stuname like "%"#{stuname}"%"
    </if>
    <if test="sno!=null and sno!=''">
        and studentno=#{sno}
    </if>
</select>
Map map=new HashMap();
map.put("stuname","张");
map.put("sno","s1101");
List<Student> students = studentDao2.findd(map);

test属性中读取属性值时直接写属性名(map类型写key值)
<select id="finde" resultType="student">
    select * from student where 1=1
    <if test="stuName!=null and stuName !=''">
        and  stuname like "%"#{stuName}"%"
    </if>
    <if test="studentNo!=null and studentNo!=''">
        and studentno=#{studentNo}
    </if>
</select>         
<!-- 相当于 select * from student where stuname like '%张%' and studentno=s1101 -->
Student student1 = new Student();
student1.setStuName("张");
student1.setStudentNo("s1101");
List<Student> students = studentDao2.finde(student1);

 

3.between and 区间查询

<select id="findf" resultType="student">
    <!--select * from student where studentid between  #{begin} and #{end}-->
    <!-- 相当于 select * from student where studentid between 1 and 5 -->
    select * from student where studentid>=#{begin} and studentid   <![CDATA[ <= ]]>  #{end}
    <!--    单独 <= 会编译报错,需要引入:<![CDATA[ <= ]]>    -->
</select>
Map map=new HashMap();
map.put("begin",1);
map.put("end",5);
List<Student> students = studentDao2.findf(map);

 

4.分⻚

方式一:RowBounds 逻辑分页

List<Student> list = session.selectList("com.yuyu.dao.StudentDao.getall",null,new RowBounds(3,3));

方式二:pageHelper分页插件 物理分页

分⻚插件的基本原理是使⽤Mybatis提供的插件接⼝,实现⾃定义插件,在插件的拦截⽅法内拦截待执⾏的sql,然后重写sql,根据dialect⽅⾔,添加对应的物理分⻚语句和物理分⻚参数。

使用前需要导入 jar 包:
分⻚插件:pagehelper.jar
sql 解析⼯具:jsqlparser.jar
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.6</version>
</dependency>
在 mybatis.xml 的 <environment defaut="devolopment">之前配置插件
<plugins>
    <!-- PageHelper4.1.6 -->
    <plugin interceptor="com.github.pagehelper.PageHelper">
        <property name="dialect" value="mysql"/>
    </plugin>
</plugins>
注意:插件5.1以后interceptor不同,并且不需要指定数据库名字
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
    </plugin>
</plugins>
//1 指定分页的参数
PageHelper.startPage(5,3);
//2 调取dao层方法
List<Student> list = session.selectList("com.yuyu.dao.StudentDao.getall");//方法参数是被调取的sql的完整路径=namespace+id
//3 创建分页工具类对象
PageInfo<Student> info = new PageInfo<Student>(list);
//4.从分页数据中获得数据
for (Student student : info.getList()) {
    System.out.println(student);
}
System.out.println("当前页条数:"+info.getSize());//                       当前页条数:3
System.out.println("总条数:"+info.getTotal());   //                       总条数:15
System.out.println("总页数:"+info.getPages());   //                       总页数:5
System.out.println("上一页:"+info.getPrePage()); //如果没有上一页,则返回0  上一页:4
System.out.println("下一页:"+info.getNextPage());//                       下一页:0
System.out.println("当前页:"+info.getPageNum()); //                       当前页:5
System.out.println("显示条数:"+info.getPageSize());//                     显示条数:3

优缺点

物理分⻚每次都要访问数据库,逻辑分⻚只访问⼀次

物理分⻚占⽤内存少,逻辑分⻚相对较多

物理分⻚数据每次都是最新的,逻辑分⻚有可能滞后

 

5.resultMap  处理列名不一致问题(多表查询)

篇幅较长,另写了一篇:

https://blog.csdn.net/qq_42183414/article/details/113485129

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值