MyBatis学习笔记4-动态SQL语句

在说动态SQL语句之前,先提两个小知识点

1. mybatis连接池的配置

主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。我们之前用的一直是池的思想

<dataSource type="POOLED">
type属性的取值:
  • POOLED 采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
  • UNPOOLED 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。

2. 自动提交

查找不需要提交事务,但增删改必须提交事务,否则对原数据没有影响。当然,如果我们不想手动提交事务,可以在创建SqlSession对象时传入true,表示自动提交事务。

SqlSession session = factory.openSession(true); 

多说一句,虽然自动提交很方便,但我们更多采用手动提交。举个简单例子,实现一个甲给乙转账的功能,若先转钱,然后提交了,这时遇到了一个bug,程序中断。最终结果是甲的钱少了,但是乙的钱并没有变多,这是有问题的。当我们手动提交时,中间遇到bug,可以设置事务回滚。这样即便中间遇到问题,甲的钱也不会变少了。


聊聊今天学习的内容,mybatis的动态SQL语句。 试想一个模糊查询功能,根据输入的姓名,住址信息,将所有满足要求的用户搜索出来。这里,有四种情况:什么都不输入,只输入一个,两个都输入。为了解决这种情况,动态SQL语句就能用上了。
1.if标签

在IUserDao中新增一个功能

//动态查询,根据用户名和地址查询
    List<User> findByUser(User user);

然后在IUserDao.xml中写主要SQL语句,如下:

<select id="findByUser" resultType="user" parameterType="user">
        select * from user where 1=1
        <if test="username != null and username != ''">
            and username like #{username}
        </if>
        <if test="address != null and address != ''">
            and address like #{address}
        </if>
</select>

这里实现的功能,主要是根据输入的姓名、住址信息进行模糊查询。在第一行写一个“1=1”,可以方便后面写and,将SQL语句连接起来。test属性中写的是对象的属性名。测试文件略。

2. where标签

就是单纯用if标签来拼接条件,我们在写条件的时候,得把 where 1=1 写上,麻烦。那能不能 不写where 和 1=1 呢?
可以,那就得使用一个标签叫where标签。
在IUserDao中新增一个功能

//动态查询,这里不写1=1
    List<User> findByAddressAndSex(User user);

然后在IUserDao.xml中写主要SQL语句,如下:

<select id="findByAddressAndSex" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="address!=null and address!=''">
                and address like#{address}
            </if>
            <if test="sex!=null and sex!=''">
                and sex like #{sex}
            </if>
        </where>
</select>

正常测试是没有问题的,这里展示一下,如果什么也不输入,测试的结果

@Test
    public void testFindByAddressAndSex(){
        User user = new User();
        List<User> users = dao.findByAddressAndSex(user);
        for (User u : users) {
            System.out.println(u);
        }
}

在这里插入图片描述
测试结果如上图所示,并不会因为没有输入用户名和地址而报错。

3. foreach标签

看一下这条语句,

SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,29,16) ;

这是一个简单的范围查询语句,但有时候,“in”中的值不能写死,而要作为参数动态添加进来。这样我们如何进行参数传递呢?
新建一个实体类,起名QueryVO,添加两个属性,一个是User对象,一个是集合ids,用来模拟要导入的id参数。如下:

public class QueryVO implements Serializable {
    User user;
    List<Integer> ids;
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public List<Integer> getIds() {
        return ids;
    }
    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
}

然后在IUserDao中新增一个功能

//动态查询,传入多个id
    List<User> findByIds(QueryVO vo);

最后在IUserDao.xml中写主要sql语句

<select id="findByIds" parameterType="QueryVO" resultType="user">
        select * from user
        <where>
            <if test="user.username!=null and user.username!=''">
                and username like #{user.username}
            </if>
            <foreach collection="ids" open="and id in(" close=")" item="uid" separator=",">
                #{uid}
            </foreach>
        </where>
</select>

解释一下foreach中几个属性的含义

  • collection:代表要遍历的集合元素,注意编写时不要写#{}
  • open:代表语句的开始部分
  • close:代表结束部分
  • item:当前遍历的集合中的元素
  • separator:分隔符
  • 最后,此sql写完整是这样的:
SELECT * FROM USER WHERE username like #{user.username} and id IN(1,2,3,4,5,28,30);

最后括号中的数据,是根据测试文件而写的。

@Test
    public void testFindByIds(){
        User user = new User();
        user.setUsername("%张%");
        List<Integer> ids= Arrays.asList(1,2,3,4,5,28,30);
        QueryVO vo = new QueryVO();
        vo.setUser(user);
        vo.setIds(ids);
        List<User> list = dao.findByIds(vo);
        for (User u : list) {
            System.out.println(u);
        }
    }

测试结果如下:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值