Java第三十七天,Mybatis框架系列,Mybatis 的动态 SQL 语句

一、<if>标签

1.格式

1=1 永真, 1<>1 永假
<select id="查询方法名" resultType="返回类型" parameterType="参数类型">
    select * from user
    <!---->
    where 1=1
    <!--if 标签中 test 属性中写的是对象的属性名-->
    <if test="判断条件">
        and 附加条件(后面有多少个条件就写多少次 and 语句)
    </if>
</select>

举例1

    <!--<if>标签的 test 属性中写的是传入对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法-->
    <!--if test 标签中能识别的变量是传入的变量;其余区域如果想要访问传入的变量需要使用 ${} 或者 #{};否则一律视为数据库表中的字段-->
    <!--功能:如果用户输入不为空,则根据输入模糊查询,如果为空,则模糊查询 username 字段中含有 1 的数据-->
    <select id="findUsersByCon" resultType="entil.User" parameterType="java.lang.String">
        select * from user
        where 1 = 1
        <if test="value != null and value != '' ">
            and username like '%${value}%'
        </if>
        <if test="value == null or value == '' ">
            and username like '%1%'
        </if>
    </select>

举例2

    <!--<if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法-->
    <!--if test 标签中能识别的变量是传入的变量;其余区域如果想要访问传入的变量需要使用 ${} 或者 #{};否则一律视为数据库表中的字段-->
    <!--功能:如果传入对象的 username 不为空,则查询模糊 username 为1的元祖;如果传入的 password 不为空则查询数据库中 password 字段和传入对象的 password 属性相同的元祖;并对结果进行与操作-->
    <select id="findUsersByCon" resultType="entil.User" parameterType="entil.User">
        select * from user
        where 1 = 1
        <!--注意,下面一行的 username 为传入参数的属性值-->
        <if test="username != '' and username != null">
            <!--注意,下面一行的第一个 username 为数据库中的字段标识,第二个 username(被${}包住)为传入变量的属性值-->
            and username like '%${username}%'
        </if>
        <!--同理;注意多个同级的 if 标签 “并联“ 时,会对所有的查询结果进行 与 操作-->
        <if test="password != '' or password != null">
            and password = #{password}
        </if>
    </select>

2.为什么要 where 1 = 1

用于应用程序根据用户选择项的不同拼凑where条件时用的

例如:查询用户的信息,where默认为1=1,这样用户即使不选择任何条件,sql查询也不会出错

如果不用1=1的话,每加一个条件,都要判断前面有没有where 条件,如果没有就要先写where ,再追加and语句,如果有就直接追加and语句,因此此时用1=1可以简化了应用程序的复杂度

优秀博文推荐:

https://blog.csdn.net/qq_36654606/article/details/86627720

二、<where>标签

1.格式

<select id="方法名" resultType="返回结果类型" parameterType="传入对象类型">
    <include refid="引用的 SQL 语句段 的ID"></include>
    <where>
        <if test="">
            and 
        </if>
        ......
    </where>
</select>

2.出现原因

where 标签的出现是为了替换掉 where 1 = 1 这段代码

3.如何使用

(1)将 where 1 = 1 删除

(2)将所有的 if 语句放在 where 标签中

举例:

    <select id="findUsersByCon" resultType="entil.User" parameterType="entil.User">
        select * from user
        <where>
            <!--注意,下面一行的 username 为传入参数的属性值-->
            <if test="username != '' and username != null">
                <!--注意,下面一行的第一个 username 为数据库中的字段标识,第二个 username(被${}包住)为传入变量的属性值-->
                and username like '%${username}%'
            </if>
            <!--同理;注意多个同级的 if 标签 “并联“ 时,会对所有的查询结果进行 与 操作-->
            <if test="password != '' or password != null">
                and password = #{password}
            </if>
        </where>
    </select>

三、foreach 标签

1.使用场景

当查询条件为一个集合时需要用到

2.格式

<foreach collection="要遍历的集合" open="数据库中的某属性 in ( " close=")" item="自定义标识"separator=",">
    #{自定义标识(必须与上面一致)}
</foreach>

collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符

3.举例

(1)实体类

package entil;

import java.io.Serializable;

public class User implements Serializable {

    private Integer officeid;
    private String username;
    private String password;

    public Integer getOfficeid() {
        return officeid;
    }

    public void setOfficeid(Integer officeid) {
        this.officeid = officeid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "officeid=" + officeid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

(2)查询条件类(包含查询条件集合综合类)

package dao;

import java.io.Serializable;
import java.util.List;

public class QueryVo implements Serializable {

    private List<Integer> ids;

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
}

(3)Dao/Mapper文件

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="dao.IUserDao">

    <!--    collection:代表要遍历的集合元素,注意编写时不要写#{}-->
    <!--    open:代表语句的开始部分-->
    <!--    close:代表结束部分-->
    <!--    item:代表遍历集合的每个元素,生成的变量名-->
    <!--    sperator:代表分隔符-->
    <!--    这段代码的意思是遍历指定的表,并将表中 officeid 字段被包含在传入变量的属性 ids(集合) 的所有元祖查询并返回-->
    <select id="findUsersByIds" resultType="entil.User" parameterType="dao.QueryVo">
        select * from user
        <where>
            <!--集合类型判断是否为空时不能 ?=='';这样会导致集合和字符串比较,会报错-->
            <!--test 里边的变量为传入变量的属性;即 ids 为 QueryVo 的属性-->
            <if test="ids != null and ids.size() > 0">
                <!--collection 用于指定要遍历的 集合对象;office 为数据库中表的字段名称-->
                <!--下面这句话的意思是遍历指定的集合,并将遍历的结果放到 开始和结束(open和close代表的两个括号的中间)-->
                <foreach collection="ids" open="and officeid in (" close=")" item="id" separator=",">
                    <!--取决于 item 定义的属性名-->
                    #{id}
                </foreach>
            </if>
        </where>
    </select>
</mapper>

(4)持久层接口类

package dao;

import entil.User;
import java.util.List;

public interface IUserDao {
    public abstract List<User> findUsersByIds(QueryVo queryVo);
}

(5)持久层接口实现类

package dao;

import entil.User;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UserDaoImpl implements IUserDao{

    private InputStream in;
    private SqlSession sqlSession;
    private IUserDao userDao;

    public UserDaoImpl(){
        try {
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //创建工厂
        //创建工厂时,mybatis使用了构建者模式,即找包工队盖房子,而不是自己亲自处理一系列问题
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        sqlSession = factory.openSession();
        userDao = sqlSession.getMapper(IUserDao.class);
    }

    // java中的析构函数
    @Override
    public void finalize(){
        sqlSession.close();
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public List<User> findUsersByIds(QueryVo queryVo) {
        return userDao.findUsersByIds(queryVo);
    }
}

(6)入口类

import dao.IUserDao;
import dao.QueryVo;
import dao.UserDaoImpl;
import entil.User;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) throws Exception{

        IUserDao userDao = new UserDaoImpl();
        QueryVo queryVo = new QueryVo();

        List<Integer> list = new ArrayList<Integer>();
        list.add(6);
        list.add(111);
        queryVo.setIds(list);

        List<User> all = userDao.findUsersByIds(queryVo);
        for(User userTemp : all){
            System.out.println(userTemp.toString());
        }
    }

}

四、引用代码片段 ===> <include refid=""></include>

1.作用

减少代码冗余度;提高可读性

2.使用

<!-- 抽取重复的语句代码片段 -->
<sql id="定义好的代码段标识ID">
    数据库语句
</sql>
<!-- 调用语句-->
<select id="" resultType="">
    <include refid="定义好的代码段标识"></include>
</select>

3.举例

        <!--表名 -->
	<sql id="tableName">
		User
	</sql>

	<!-- 字段 -->
	<sql id="Field">
		INDEX_CODE,
		INDEX_NAME,
		INDEX_CAL_TYPE,
		INDEX_DATA_TYPE,
		UUID
	</sql>

	<!-- 字段值 -->
	<sql id="FieldValue">
		#{indexCode},
		#{indexName},
		#{indexCalType},
		#{indexDataType},
		#{uuid}
	</sql>

	<!-- 通过ID获取数据 -->
	<select id="findByIndexId" parameterType="String" resultType="User">
		select
		<include refid="Field"></include>
		from
		<include refid="tableName"></include>
		where
		UUID = #{indexId}
	</select>

 

 

posted @ 2020-08-01 17:22  IT蓝月  阅读(106)  评论(0编辑  收藏  举报
Live2D