【MyBatis 】之 Mybatis 动态 SQL 语句-08

本文详细介绍了Mybatis中动态SQL的使用,包括if、where和foreach标签的实战应用,以及如何通过定义SQL片段实现代码复用。通过实例展示了如何根据用户输入动态拼接SQL查询,以及处理集合参数查询的方法。最后,演示了如何在映射配置中引用SQL片段,以提高代码效率。
摘要由CSDN通过智能技术生成

1. Mybatis 动态 SQL 语句

1.1 Mybatis环境搭建

第一步:创建 maven 工程
在这里插入图片描述
第二步:导入坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.spg</groupId>
    <artifactId>mybatis_day02_curd</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>

</project>

第三步:创建数据库,编写必要代码(实体类和持久层接口)

CREATE TABLE `user`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名称',
  `birthday` datetime NULL DEFAULT NULL COMMENT '生日',
  `sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',
  `address` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 49 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
package com.spg.entity;

import java.util.Date;

public class User {
    private Integer id;
    private String userName;
    private String address;
    private String sex;
    private Date birthday;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", address='" + address + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}
package com.spg.dao;

import com.spg.entity.User;

/**
 * 用户的持久层接口
 */
public interface UserDao {
}

第四步:编写 mybatis-config.xml

<?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">
<!-- mybatis的主配置文件 -->
<configuration>
    <!-- 配置环境 -->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务的类型-->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_db?serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
    <mappers>
        <mapper resource="mapper/UserDao.xml"/>
    </mappers>
</configuration>

第五步:编写映射配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.spg.dao.UserDao">
</mapper>

第六步:编写测试类

package com.spg.test;

import com.spg.dao.UserDao;
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.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class MybatisTest {

    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private UserDao userDao;

    @Before // 在测试方法执行之前执行
    public void init() throws IOException {
        // 1.读取配置文件
        in = Resources.getResourceAsStream("mybatis-config.xml");
        // 2.创建构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3.创建SqlSession工厂对象
        factory = builder.build(in);
        // 4.创建SqlSession对象
        sqlSession = factory.openSession();
        // 5.创建Dao的代理对象
        userDao = sqlSession.getMapper(UserDao.class);
    }

    @After // 在测试方法执行之后执行
    public void destroy() throws IOException {
    	// 实现事务提交
        sqlSession.commit();
        // 7. 释放资源
        sqlSession.close();
        in.close();
    }

    @Test
    public void testMethod() {
        // 6.执行操作
    }
}

1.1 动态 SQL 之 if 标签

1.1.1 持久层 Dao 接口

/**
 * 根据用户信息,查询用户列表
 * @param user
 * @return
 */
List<User> findByUser(User user);

1.1.2 持久层 Dao 映射配置

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

注意: <if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。
另外要注意 where 1=1 的作用~!

1.1.3 测试类中添加测试方法

public class MybatisTest {

    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private UserDao userDao;

    @Before // 在测试方法执行之前执行
    public void init() throws IOException {
        // 1.读取配置文件
        in = Resources.getResourceAsStream("mybatis-config.xml");
        // 2.创建构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 3.创建SqlSession工厂对象
        factory = builder.build(in);
        // 4.创建SqlSession对象
        sqlSession = factory.openSession();
        // 5.创建Dao的代理对象
        userDao = sqlSession.getMapper(UserDao.class);
    }

    @After // 在测试方法执行之后执行
    public void destroy() throws IOException {
        sqlSession.commit();
        // 7. 释放资源
        sqlSession.close();
        in.close();
    }
    
	@Test
	public void testFindByUser() {
		User u = new User();
		u.setUsername("%王%");
		u.setAddress("%北京%");
		//6.执行操作
		List<User> userList = userDao.findByUser(u);
		for(User user : userList) {
			System.out.println(user);
		}
	}
}

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

1.2 动态 SQL 之 where 标签

为了简化上面 where 1=1 的条件拼装,可以采用<where>标签来简化开发。
持久层 Dao 映射配置:

<!-- 根据用户信息查询 -->
<select id="findByUser" resultType="user" parameterType="user">
	select * from user
	<where>
		<if test="username!=null and username != '' ">
			and username like #{username}
		</if>
		<if test="address != null">
			and address like #{address}
		</if>
	</where>
</select>

1.3 动态 SQL 之 foreach 标签

1.3.1 需求

传入多个 id 查询用户信息,用下边两个 sql 实现:

SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)

这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。
这样我们将如何进行参数的传递?

1.3.2 在 QueryVo 中加入一个 List 集合用于封装参数

public class QueryVo{

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

1.3.3 持久层 Dao 接口

/**
 * 根据 id 集合查询用户
 * @param vo
 * @return
 */
List<User> findInIds(QueryVo vo);

1.3.4 持久层 Dao 映射配置

<!-- 
SQL 语句:
	select 字段 from user where id in (?)
	<foreach>标签用于遍历集合,它的属性:
		collection:代表要遍历的集合元素,注意编写时不要写#{}
		open:代表语句的开始部分
		close:代表结束部分
		item:代表遍历集合的每个元素,生成的变量名
		sperator:代表分隔符
-->
<!-- 查询所有用户在 id 的集合之中 -->
<select id="findInIds" resultType="com.spg.entity.User" parameterType="com.spg.entity.QueryVo">
	<!-- select * from user where id in (1,2,3,4,5); -->
	select * from user
	<where>
		<if test="ids != null and ids.size() > 0">
			<foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">
				#{uid}
			</foreach>
		</if>
	</where>
</select>

1.3.5 测试类中添加测试方法

@Test
public void testFindInIds() {
	QueryVo vo = new QueryVo();
	List<Integer> ids = new ArrayList<Integer>();
	ids.add(41);
	ids.add(42);
	ids.add(43);
	ids.add(46);
	ids.add(57);
	vo.setIds(ids);
	//6.执行操作
	List<User> userList = userDao.findInIds(vo);
	for(User user : userList) {
		System.out.println(user);
	}
}

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

1.4 Mybatis 中简化编写的 SQL 片段

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。

1.4.1 定义代码片段

<!-- 抽取重复的语句代码片段 -->
<sql id="defaultSql">
	select * from user
</sql>

1.4.2 引用代码片段

<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.spg.entity.User">
	<include refid="defaultSql"></include>
</select>
<!-- 根据 id 查询 -->
<select id="findById" resultType="com.spg.entity.User" parameterType="int">
	<include refid="defaultSql"></include>
	where id = #{uid}
</select>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值