Mybaits动态SQL课堂笔记

一、动态SQL中的元素

1.简介

用于在MyBatis的映射文件中动态组装SQL语句
主元素如下:**
在这里插入图片描述

2. 实验环境

  • 第一步,在ssm_mybatis项目下建mybatis-chap03-sql模块
  • 第二步,导入mybatis、mysql、junit包
    目录结构与导包参考Mybatis案例
  • 第三步,创建数据库mybatis,建表t_customer。建表语句如下:
USE mybatis;
CREATE TABLE t_customer (
id int(32) PRIMARY KEY AUTO_INCREMENT,
username varchar(50),
jobs varchar(50),
phone varchar(16));
INSERT INTO t_customer VALUES ('1', 'joy', 'teacher', '13733333333');
INSERT INTO t_customer VALUES ('2', 'jack', 'teacher', '13522222222');
INSERT INTO t_customer VALUES ('3', 'tom', 'worker', '15111111111');
  • 第四步,创建POJO类Customer,各字段与表t_customer字段一致(放pojo包中)
package com.cshbxy.pojo;
public class Customer {
private int id;
private String username;
private String jobs;
private String phone;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getJobs() {
return jobs;
}
public void setJobs(String jobs) {
this.jobs = jobs;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", username='" + username + '\'' +
", jobs='" + jobs + '\'' +
", phone='" + phone + '\'' +
'}';
}
}
  • 第五步,创建Mapper接口CustomerMapper,对需要的操作进行定义(放mapper包)
package com.cshbxy.mapper;
import com.cshbxy.pojo.Customer;
import java.util.List;
import java.util.Map;
public interface CustomerMapper {
/*完成if元素实验。实验要求:按姓名和职业查询,如果查询值为空或空串,则不纳入条件*/
List<Customer> selectByNameAndJobs_if(Customer customer);
/*完成choose when otherwise元素实验。实验要求:仅按姓名或职业中的某个给定条件查询(查询
值为空或空串,不纳入条件),如果姓名、职业均未给定查询值,则查询手机号非空用户*/
List<Customer> selectByNameOrJobs_choose(Customer customer);
/*完成where实验。实验要求:按姓名或职业查询,如果查询值为空或空串,则不纳入条件*/
List<Customer> selectByNameAndJobs_where(Customer customer);
/*完成trim实验。实验要求:按姓名或职业查询,如果查询值为空或空串,则不纳入条件*/
List<Customer> selectByNameAndJobs_trim(Customer customer);
/*完成set实验。实验要求:按id更新记录,只修改给定属性值不为空和空串的字段*/
int updateById_set(Customer customer);
/*完成trim实验。实验要求:按id更新记录,只修改给定属性值不为空和空串的字段*/
int updateById_trim(Customer customer);
/*完成foreach遍历数组实验。实验要求:查询id值为多个指定值的记录。多个id值通过数组传入*/
List<Customer> selectById_Arrays(int[] ids);
/*完成foreach遍历数组实验。实验要求:查询id值为多个指定值的记录。多个id值通过List传入*/
List<Customer> selectById_List(List<Integer> ids);
/*完成foreach遍历Map实验。实验要求:仅显示id值为数组元素值的记录。多个id值通过Map传入*/
List<Customer> selectById_Map(Map ids);
/*完成参数为Map的实验。实验要求:查询记录,查询字段及值由Map给定(即:查询条件有不确定性,
由用户给出)。
 - 此种情况下,Map传入多参数时要求用户调用给定实参时,实参的键值必须是表字段名,否则会出错。
*/
List<Customer> selectByUnConditon(Map customer);
}
  • 第六步,为上述接口创建映射文件CustomerMapper.xml(放resources的mapper文件夹下),实

现各方法的sql映射在后续示例中给出。注意两个问题: 映射文件命名空间namespace为上述接口的全限定名
com.lyrpx.mapper.CustomerMapper
为了方便,类的名称均采用包扫描默认别名,后续记得在核心配置文件中进行包扫描别名配置
一般情况下,写完一个测试一个。所以,可以写完第一个映射语句就去配置核心配置文件,之后测试!

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyrpx.mapper.CustomerMapper">
<!--分别完成CustomerMapper接口中定义的所有方法的SQL映射-->
</mapper>
  • 第七步,创建Mybatis核心配置文件mybatis-config.xml(放resources文件夹)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入属性文件。可以配置多个properties元素-->
<properties resource="db.properties"/>
<!--采用包扫描方式定义别名。其内部可以配置多个package元素-->
<typeAliases>
<package name="com.cshbxy.pojo"/>
</typeAliases>
<!--配置数据源。可以多套environment,由default属性仁决定使用哪套!-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件。其内部可以配置多个mapper元素-->
<mappers>
<mapper resource="mapper/CustomerMapper.xml"/>
</mappers>
</configuration>
  • 第八步,编写测试类TestCustomerMapper(放test\java文件夹),此处给模板,后续自己按模板
    添加单元测试
  • 模板一:创建会话对象时,没有带参数
import com.cshbxy.mapper.CustomerMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class TestCustomerMapper {
@Test
public void testIf() throws IOException {
//第一大步,创建会话对象sqlSession
InputStream in = Resources.getResourceAsStream("mybatisconfig.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession=factory.openSession();
//第二大步,通过会话对象的getMapper()方法实现接口CustomerMapper,并获取该对象
CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
//第三大步,完成测试(此处自己针对实现的方法进行测试)
/*
第四大步,关闭会话对象。如果是增、删、修改操作,关闭之前还要提交事务。语句如下:
sqlSession.commit();
*/
sqlSession.close();
}
}
  • 模板二:创建会话对象时,带true参数
import com.cshbxy.mapper.CustomerMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class TestCustomerMapper {
@Test
public void testIf() throws IOException {
//第一大步,创建会话对象sqlSession
InputStream in = Resources.getResourceAsStream("mybatisconfig.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession=factory.openSession(true); //true:关闭时自动提交
事务
//第二大步,通过会话对象的getMapper()方法实现接口CustomerMapper,并获取该对象
CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
//第三大步,完成测试(此处自己针对实现的方法进行测试)
//第四大步,关闭会话对象。因为之前创建事务时带true参数,所以此处不必考虑事务提交问题
sqlSession.close();
}
}

二、条件查询操作

1.if元素

  • 作用:用于单条件判断,条件满足时拼装其内部SQL代码。该元素经常与其它元素联合使用。
  • 注意事项:
  • if前面要写where 1=1
  • 引用传入参数值语法:#{属性名},属性名必须与传入参数类定义中的一致
<!--完成if元素实验。实验要求:按姓名和职业查询,如果查询值为空或空串,则不纳入条件-->
<select id="selectByNameAndJobs_if" resultType="customer">
select * from mybatis.t_customer where 1=1
/*分析:if元素,条件满足时才拼装SQL语句*/
<if test="username!=null and username!=''">
and username=#{username}
</if>
<if test="jobs!=null and jobs!=''">
and jobs=#{jobs}
</if>
</select>

2.choose、when、otherwise元素

  • 作用:用于多分支条件判断,只拼装首个满足条件的when内部SQL代码,均不满足则拼装otherwise内部SQL代码。
  • 注意事项:
  • if前面要写where 1=1
  • 引用传入参数值语法:#{属性名},属性名必须与传入参数类定义中的一致
  • 只会执行一个条件语句,或均不执行
  • otherwise可以不写
<!--完成choose when otherwise元素实验。仅按姓名或职业中的某个给定条件查询(查询值为空或
空串,不纳入条件),如果姓名、职业均未给定查询值,则查询手机号非空用户-->
<select id="selectByNameOrJobs_choose" resultType="customer">
select * from mybatis.t_customer where 1=1
/*分析:choose元素仅拼装第一个满足条件的SQL语句*/
<choose>
<when test="username!=null and username!=''">
and username = #{username}
</when>
<when test="jobs!=null and jobs!=''">
and jobs = #{jobs}
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</select>

3.where、trim元素

(1)where元素

  • 作用:自动判断是否加where关键字,或去除不必要的逻辑运算符。
  • 注意事项:
  • 不要写where 1=1
  • 引用传入参数值语法:#{属性名},属性名必须与传入参数类定义中的一致
  • where内部要写条件拼装语句
<!--完成where实验。实验要求:按姓名或职业查询,如果查询值为空或空串,则不纳入条件-->
<select id="selectByNameAndJobs_where" resultType="customer">
select * from mybatis.t_customer
/*分析:where元素会根据内部的拼装语句自动判断是否加where,及是否去除and*/
<where>
<if test="username!=null and username!=''">
and username=#{username}
</if>
<if test="jobs!=null and jobs!=''">
and jobs=#{jobs}
</if>
</where>
</select>

(2)trim元素

  • 常用属性
    在这里插入图片描述
  • 作用
  • 自动判断是否在拼装语句的最前面加prefix属性给定的前缀值,去除prefixOverrides属性给定 的前缀字符串;
  • 自动判断是否在拼装语句的最后面加suffix 属性给定的后缀值,去除suffixOverrides属性给定的后缀字符串。
  • 注意事项:
  • 引用传入参数值语法:#{属性名},属性名必须与传入参数类定义中的一致
  • trim内部要写条件拼装语句
  • 要加入的前缀、后缀,及要去除的前缀、后缀值不要赋错了属性
<!--完成trim实验。实验要求:按姓名或职业查询,如果查询值为空或空串,则不纳入条件-->
<select id="selectByNameAndJobs_trim" resultType="customer">
select * from mybatis.t_customer
/*分析:trim元素会根据内部的拼装语句自动判断是否加前缀where,及是否去除前缀and*/
<trim prefix="where" prefixOverrides="and">
<if test="username!=null and username!=''">
and username=#{username}
</if>
<if test="jobs!=null and jobs!=''">
and jobs=#{jobs}
</if>
</trim>
</select>

三、更新操作

1.set元素实现

作用:自动判断是否加set关键字,是否去除逗号。

<!--完成set实验。实验要求:按id更新记录,只修改给定属性值不为空和空串的字段-->
<update id="updateById_set">
update mybatis.t_customer
/*分析:set元素自动判断是否加set关键字,是否去除逗号*/
<set>
<if test="username!=null and username!=''">
username=#{username},
</if>
<if test="jobs!=null and jobs!=''">
jobs=#{jobs},
</if>
<if test="phone!=null and phone!=''">
phone=#{phone},
</if>
</set>
where id=#{id}
</update>

2.trim元素实现

trim也可以实现更新操作,具体用法见前述。

<!--完成trim实验。实验要求:按id更新记录,只修改给定属性值不为空和空串的字段-->
<update id="updateById_trim">
update mybatis.t_customer
/*分析:trim元素自动判断是否加前缀set,是否去除后缀字符串逗号*/
<trim prefix="set" suffixOverrides=",">
<if test="username!=null and username!=''">
username=#{username},
</if>
<if test="jobs!=null and jobs!=''">
jobs=#{jobs},
</if>
<if test="phone!=null and phone!=''">
phone=#{phone},
</if>
</trim>
where id=#{id}
</update>

测试代码


public class TestCustomerMapper {
    @Test
    public void testIf() throws IOException {
//获取会话对象sqlSession
        SqlSession sqlSession= MyTool.getSqlSession();
        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
//完成测试(此处自己针对实现的方法进行测试)
        Customer cc=new Customer();
        cc.setJobs("teacher");
        List<Customer> customers=mapper.selectByNameAndJobs_if(cc);
        for (Customer customer : customers){
            System.out.println(customer);
        }
        sqlSession.close();
    }
    @Test
    public void testChoose(){
        SqlSession sqlSession = MyTool.getSqlSession();

        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);

        Customer customer=new Customer();
        customer.setUsername("tom");
        customer.setJobs("teacher");

        List<Customer> customers= sqlSession.selectList("com.lyrpx.mapper.CustomerMapper.selectByNameOrJobs_choose",customer);
        for (Customer customer1 : customers) {
            System.out.println(customer1);

        }
        //关闭会话
        sqlSession.close();
    }

    @Test
    public void TestWhere(){
        SqlSession sqlSession = MyTool.getSqlSession();

        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);

        Customer customer=new Customer();
        customer.setUsername("jack");
        customer.setJobs("teacher");

        List<Customer> customers= sqlSession.selectList("com.lyrpx.mapper.CustomerMapper.selectByNameOrJobs_choose",customer);
        for (Customer customer2 : customers) {
            System.out.println(customer2);

        }
        //关闭会话
        sqlSession.close();
    }

    @Test
    public void TestTrim(){
        SqlSession sqlSession = MyTool.getSqlSession();

        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);

        Customer customer=new Customer();
        customer.setUsername("jack");
        customer.setJobs("teacher");

        List<Customer> customers= sqlSession.selectList("com.lyrpx.mapper.CustomerMapper.selectByNameOrJobs_choose",customer);
        for (Customer customer3 : customers) {
            System.out.println(customer3);

        }
        //关闭会话
        sqlSession.close();
    }

    @Test
    public void TestSet(){
        SqlSession sqlSession = MyTool.getSqlSession();

        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);

        Customer customer=new Customer();
        customer.setId(3);
        customer.setPhone("13142123762");
        int rows=sqlSession.update("com.lyrpx.mapper.CustomerMapper.updateById_set",customer);

        if (rows>0){
            System.out.println("您修改了"+rows+"条数据");
        }else {
            System.out.println("执行修改操作失败!");
        }
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void TestUpdateTrim(){
        SqlSession sqlSession = MyTool.getSqlSession();

        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);

        Customer customer=new Customer();
        customer.setId(3);
        customer.setPhone("10086");
        int rows=sqlSession.update("com.lyrpx.mapper.CustomerMapper.updateById_set",customer);

        if (rows>0){
            System.out.println("您修改了"+rows+"条数据");
        }else {
            System.out.println("执行修改操作失败!");
        }
        sqlSession.commit();
        sqlSession.close();
    }
}

四、复杂查询操作

1.foreach元素及其属性

  • 作用:用于遍历传入的集合类型参数数据。(迭代就是遍历的意思)
  • 常用属性
    在这里插入图片描述

2.foreach元素迭代数组

  • 注意事项:

collection属性值为array
使用#{参数名}引入传入参数值时,参数名必须与item属性值一致
一般用于sql中的in运算。如:in(2,3,5)

<!--完成foreach遍历数组实验。实验要求:查询id值为多个指定值的记录。多个id值通过数组传
入-->
<select id="selectById_Arrays" resultType="Customer">
select * from mybatis.t_customer
where id in
<foreach collection="array" item="id" separator="," open="("
close=")" >
#{id}
</foreach>
</select>

3.foreach元素迭代List

  • 注意事项:

collection属性值为list
使用#{参数名}引入传入参数值时,参数名必须与item属性值一致
一般用于sql中的in运算。如:in(2,3,5)

<!--完成foreach遍历列表验。实验要求:查询id值为多个指定值的记录。多个id值通过List传
入-->
<select id="selectById_List" resultType="Customer">
select * from mybatis.t_customer
where id in
<foreach collection="list" item="id" open="(" close=")"
separator=",">
#{id}
</foreach>
</select>

4.foreach元素迭代Map

  • 注意事项:

collection属性值为传入map的某个key的名称
使用#{参数名}引入传入参数值时,参数名必须与item属性值一致
一般用于sql中的in运算。如:in(2,3,5)

<!--完成foreach遍历Map实验。实验要求:查询id值为多个指定值的记录。多个id值通过Map传
入-->
<select id="selectById_Map" resultType="Customer">
select * from mybatis.t_customer
where id in
<foreach collection="id" item="value" open="(" close=")"
separator=",">
#{value}
</foreach>
</select>
<!--完成参数为Map的实验。实验要求:查询指定职业,且id值为多个指定值的记录。
此种情况下需要Map传入多参数,要求用户给定实参时,实参的键值必须是表字段名,否则会出
错。-->
<select id="selectByMutilConditon" resultType="Customer">
select * from mybatis.t_customer
where jobs=#{jobs}
and id in
<foreach collection="id" item="value" open="(" close=")"
separator=",">
#{value}
</foreach>
</select>

五、案例:学生信息查询系统

在这里插入图片描述
数据表生成代码如下:

DROP TABLE IF EXISTS `dm_student`;
CREATE TABLE `dm_student` (
`id` int(32) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`major` varchar(50) DEFAULT NULL,
`sno` varchar(16) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of dm_student
-- ----------------------------
INSERT INTO `dm_student` VALUES ('1', '张三', '数学', '10001');
INSERT INTO `dm_student` VALUES ('2', '李四', '英语', '10002');
INSERT INTO `dm_student` VALUES ('3', '王五', '计算机', '10003');
INSERT INTO `dm_student` VALUES ('4', '王刚', '化学', '10004');
INSERT INTO `dm_student` VALUES ('5', '李华', '物理', '10005');
INSERT INTO `dm_student` VALUES ('6', '李雷', '中文', '10006');
INSERT INTO `dm_student` VALUES ('7', '张飞', '英语', '10007');
INSERT INTO `dm_student` VALUES ('9', '刘小小', '地理', '10001');

1.该系统要求实现以下功能
(1)单条件查询:按id查询学生信息。(方法名:findById)
(2)多条件查询(方法名:findStudentByNameOrMajor)
当用户输入的学生姓名不为空,则只根据学生姓名进行学生信息的查询;
当用户输入的学生姓名为空,而学生专业不为空,则只根据学生专业进行学生的查询;
(3)foreach遍历查询:按用户给定的多个专业查询学生信息。用如下三种方法完成:
多个专业值放在一个数组中传入。(方法名:findByMajor_Arrays)
多个专业值放在一个List中传入。(方法名:findByMajor_List)
多个专业值放在一个Map中传入。(方法名:findByMajor_Map)
(4)按id值修改学生信息,条件及修改的值用一个对象传入。(方法名:updateById)
2.完成如下测试

  • (1)测试查询出所有id值小于5的学生的信息。
  • (2)查询出数学、英语、计算机专业的学生信息。
  • (3)查询出有所专业值非空的学生信息。
  • (4)修改id值为2的学生专业为数学

案例整理完上传!

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
数据库迭代查询作业 emp(eno, ename, salary, mgr),其中mgr是员工领导,设计约束:要求领导的工资不能低于他的下属平均工资。(注意,这是一个递归查询) 下面是一些样例数据 CREATE TABLE dbo.Employees ( empid INT NOT NULL PRIMARY KEY, mgrid INT NULL REFERENCES dbo.Employees, empname VARCHAR(25) NOT NULL, salary MONEY NOT NULL, CHECK (empid mgrid) ); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(1, NULL, 'David', $10000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(2, 1, 'Eitan', $7000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(3, 1, 'Ina', $7500.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(4, 2, 'Seraph', $5000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(5, 2, 'Jiru', $5500.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(6, 2, 'Steve', $4500.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(7, 3, 'Aaron', $5000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(8, 5, 'Lilach', $3500.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(9, 7, 'Rita', $3000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(10, 5, 'Sean', $3000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(11, 7, 'Gabriel', $3000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(12, 9, 'Emilia' , $2000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(13, 9, 'Michael', $2000.00); INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES(14, 9, 'Didi', $1500.00);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TechLens

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值