1 初识MyBatis框架
1.1 MyBatis框架简述
MyBatis 是一个基于 Java 的持久层框架、半自动的ORM框架,它封装了 JDBC API,提供了一个简单、灵活的方式来处理数据库中的数据。MyBatis 允许开发者通过 XML 或注解来配置 SQL 语句,从而避免了直接编写 JDBC 代码的复杂性。
1.2 数据的持久化及ORM
1.2.1 持久化简介
持久化(Persistence)是指将数据从内存中保存到磁盘或其他持久存储介质中,以便在应用程序关闭或系统重启后能够重新加载数据。持久化的主要目的是确保数据的持久性和可靠性,即使在断电或系统故障的情况下,数据也不会丢失。
持久化的实现方式
1.文件存储:将数据以文件的形式存储在磁盘上。
2.数据库存储:将数据存储在关系型数据库或非关系型数据库中。
3.对象关系映射(ORM):将对象模型和关系数据库之间进行映射,使得开发者可以使用面向对象的方式来操作数据库。
4.缓存存储:将数据存储在内存中的缓存中,提高数据的读取和访问速度。
1.2.2 ORM简介
ORM(Object Relational Mapping,对象关系映射)是一种编程技术,用于在关系数据库和对象程序语言之间转换数据。ORM框架允许开发者以面向对象的方式来操作数据库,而不需要编写复杂的SQL语句。简单来说,ORM通过描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中
ORM的核心优势:
1.提高开发效率:ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,减少了手动编写SQL的工作量。
2.简化代码:面向对象的编程方式使得代码更加简洁、易读。
3.跨数据库支持:ORM框架通常支持多种数据库,便于项目迁移和扩展。
4.减少SQL注入风险:ORM框架通常内置了防止SQL注入的机制
1.2.2.1 半自动ORM
半自动的ORM(Object Relational Mapping)框架是一种介于全自动ORM框架和手动编写SQL之间的解决方案。这种类型的框架通常提供了一些自动化的功能,如对象关系映射、查询结果集的自动映射等,但仍然需要开发者手动编写部分SQL语句。
半自动ORM框架的特点
1.手动编写SQL:开发者需要手动编写部分SQL语句,这给予了开发者对SQL查询的高度控制权,可以根据实际需求优化SQL。
2.SQL映射定义:虽然提供了映射文件(如XML配置文件)来定义Java对象与数据库表之间的映射关系,但关联对象或集合的查询仍然需要通过手动编写的SQL来完成。
3.结果集映射:支持自动将查询结果映射到Java对象,但映射规则需要手动定义。
4.灵活性和性能优化:由于开发者直接控制SQL语句,因此在性能优化方面具有较高的灵活性。
1.2.2.1 全自动ORM
全自动的ORM(Object Relational Mapping)框架是一种对象关系映射技术,它允许开发者使用面向对象的方式来操作数据库,而无需编写大量的SQL语句。这种框架通常会自动处理对象和数据库表之间的映射关系,以及数据的持久化操作。
全自动ORM框架的特点
1.自动生成SQL语句:全自动ORM框架能够根据对象模型自动生成相应的SQL语句,这大大减少了开发者编写SQL的工作量。
2.对象关系映射:框架会自动处理对象和数据库表之间的映射关系,使得开发者可以通过操作对象来实现对数据库的操作。
2.数据持久化:框架提供了数据持久化的功能,能够自动将对象的状态保存到数据库中,或者从数据库中恢复对象的状态。
3.事务管理:全自动ORM框架通常提供了事务管理的功能,能够确保数据库操作的原子性、一致性、隔离性和持久性。
1.3 在Maven环境搭建基于MyBatis框架的开发环境
在项目中使用MyBatis框架可以按照以下步骤进行。
- 创建Maven项目
- 配置pom.xml
<?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>org.example</groupId>
<artifactId>ktmall_myBatis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--mybatis 3.5.16-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16</version>
</dependency>
<!--log4j 1.2.17-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--mysql 8.3.0-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
- 编写MyBatis的核心配置文件(文件位置:resources目录下)
3.1. 创建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">
<configuration>
<!-- 引用包含数据库连接参数 database.properties -->
<properties resource="database.properties"/>
<!-- 1.设置MyBatis框架的运行时行为 -->
<settings>
<!-- 设置日志 -->
<setting name="logImpl" value="LOG4J"/>
<!-- 设置下划线命名转换为驼峰命名 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
<!-- 设置自动映射行为 PARTIAL:嵌套不映射 FULL:嵌套映射-->
<setting name="autoMappingBehavior" value="FULL"/>
</settings>
<typeAliases>
<!-- 配置别名,让实体类与数据库表字段一致,导入是文件夹 -->
<package name="org.ktmall.entity"/>
</typeAliases>
<!--2.配置MyBatis框架的运行环境 default默认id连接数据库 -->
<environments default="development">
<environment id="development">
<!-- 配置事务管理器,采用JBDC事务,由应用自行管理事务 -->
<transactionManager type="JDBC"/>
<!-- 配置数据源,POOLED:MyBatis提供的数据源,JNDI:JNDI 数据源 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- <mapper resource="org/example/mapper/SysUserMapper.xml"/>-->
<!-- <mapper class="org.ktmall.mapper.SysUserMapperTest"/>-->
<!-- 导入文件夹的所有mapper文件 -->
<package name="org.ktmall.mapper"/>
</mappers>
</configuration>
3.2. 创建database.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=UTF-8
username=xxx
password=xxx
3.3. 创建log4j.properties(设置日志规则,可以根据自己需求修改)
# 设置根日志级别为DEBUG,输出目标为控制台和文件
log4j.rootLogger=DEBUG, stdout, file
# 控制台输出设置
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p [%t] %c{2} - %m%n
# 文件输出设置
log4j.appender.file=org.apache.log4j.FileAppender
# 文件存储路径,可以根据实际需求修改
log4j.appender.file.File=logs/application.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-5p [%t] %c{2} - %m%n
- 创建实体类(不过多描述)
- 创建mapper
创建mapper接口为:java/org/项目名称/mapper/UserMapper.java
public interface WxUserMapper {
int count();
}
mapper.xml注意创建位置
xml文件模板:
<?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="org.ktmall.mapper.WxUserMapper">
<select id="count" resultType="java.lang.Integer">
select count(1) from t_wx_user
</select>
</mapper>
第一种:位置为:src/java/org/项目名称/mapper/UserMapper.xml
第二种:位置为:src/main/resources/org/项目名称/mapper/UserMapper.xml
原因:项目编译必须把mapper接口文件和xml文件放在编译文件同一目录下否则接口文件无法找到xml文件。
- 创建 MyBatisUtil
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.io.InputStream;
public class MyBatisUtil {
private static SqlSessionFactory factory;
// 静态代码块,在类加载的时候就执行,只执行一次
static {
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
factory = new org.apache.ibatis.session.SqlSessionFactoryBuilder().build(is);
} catch (Exception e) {
throw new RuntimeException("获取数据连接失败",e);
}
}
/**
* 获取SqlSession对象
* @param autoCommit 是否自动提交事务
* @return 数据库连接对象 SqlSession
*/
public static SqlSession createSqlSession(Boolean autoCommit){
return factory.openSession(autoCommit);
}
/**
* 关闭SqlSession对象
* @param session 要关闭的SqlSession对象
*/
public static void closeSqlSession(SqlSession session){
if(session!=null){
session.close();
}
}
}
- 目录
- 测试
在Maven初步创建MyBatis项目完成。
2 SQL映射文件详解
2.1 详解
映射文件的基本结构
MyBatis的SQL映射文件通常具有.xml扩展名,并且与对应的Mapper接口位于相同的包路径下。其基本结构包括根标签,内部包含各种数据库操作的定义,如<select>、<insert>、<update>和<delete>等标签。
主要元素和属性
- <mapper>元素
1.1 namespace属性:用于区分不同的mapper,必须全局唯一。通常与Mapper接口的全限定名相同,以便MyBatis自动映射SQL语句和Java方法。
<select>元素
1.2 id属性:在命名空间中唯一的标识符,可用于引用这条语句。
1.3 parameterType属性:传入SQL语句的参数类型,可以是基础数据类型或复杂数据类型。
1.4 esultType属性:SQL语句返回值的类型,可以是基础数据类型或复杂数据类型。
1.5 resultMap属性:对外部resultMap的命名引用,用于处理复杂的结果映射。 - <insert>、<update>和<delete>元素
2.1 id属性:在命名空间中唯一的标识符,可用于引用这条语句。
2.2 parameterType属性:传入SQL语句的参数类型,可以是基础数据类型或复杂数据类型。
2.3 useGeneratedKeys属性(仅适用于<insert>和<update>):设置为true时,MyBatis会使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键。
2.4 keyProperty属性(仅适用于<insert>和<update>):指定能够唯一识别对象的属性,MyBatis会使用getGeneratedKeys的返回值或insert语句的selectKey子元素设置它的值。 - <resultMap>元素
3.1 id属性:唯一标识,用于元素resultMap的引用。
3.2 type属性:表示resultMap的映射结果类型。
3.3 <id>子标签:用于标识主键列,提高程序效率。
3.4 <result>子标签:用于标识属性。
3.5 <association>子标签:处理一对一的关联关系。
3.6 <collection>子标签:处理一对多的关联关系。 - <sql>元素:id属性:定义可重用的SQL代码片段的唯一标识符。
2.2 实践
- 实体类
import java.time.*;
import lombok.Data;
import java.io.Serializable;
/**
* 系统角色(SysRole)表实体类
*
* @author makejava
* @since 2024-11-19 15:09:35
*/
@Data
public class SysRole implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long id;
/**
* 角色编码
*/
private String code;
/**
* 角色名称
*/
private String roleName;
/**
* 创建者
*/
private Long createdUserId;
/**
* 创建时间
*/
private LocalDateTime createdTime;
/**
* 修改者
*/
private Long updatedUserId;
/**
* 修改时间
*/
private LocalDateTime updatedTime;
}
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.List;
/**
* 系统用户(SysUser)表实体类
*
* @author makejava
* @since 2024-11-15 19:00:16
*/
@Data
public class SysUser implements Serializable{
//主键ID
private Long id;
//账号
private String account;
//真实姓名
private String realName;
//密码
private String password;
//性别(1:女、 2:男)
private Integer sex;
//出生日期(年-月-日)
private LocalDate birthday;
//手机号码
private String phone;
//用户地址
private String address;
//用户角色id
private Long roleId;
//创建人
private Long createdUserId;
//创建时间
private LocalDateTime createdTime;
//修改人
private Long updatedUserId;
//修改时间
private LocalDateTime updatedTime;
//角色名称
private String userRoleName;
/**
* 系统角色实体
*/
private SysRole sysRole;
/**
* 用户地址集合
*/
private List<Address> addressList;
}
- mapp接口
import org.apache.ibatis.annotations.Param;
import org.example.entity.SysUser;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* @author HT
* @title SysUserMapper
* @date 2024/11/15 19:14
* @description TODO
*/
public interface SysUserMapper {
/**
* 统计用户数量
* @return
*/
public int count();
List<SysUser> getUserList();
List<SysUser> getUsersByRealName(@Param("name") String name);
List<SysUser> getUserListByMap(Map<String, Object> map);
List<SysUser> getUserListByParams(@Param("realName") String realName, @Param("roleId") int roleId);
List<SysUser> getUserListWithRoleName(SysUser sysUser);
/**
* 根据角色id查询用户列表,包含系统角色
* @param roleId 角色id
* @return
*/
List<SysUser> getUserListByRoleId(@Param("roleId") Integer roleId);
List<SysUser> getUserAndAddressesByUserId(@Param("userId") Integer userId);
/**
* 新增用户
* @param sysUser 用户对象
* @return int 新增数量
*/
int add(SysUser sysUser);
int update(SysUser sysUser);
/**
* 修改密码
* @param id 用户id
* @param password 新密码
* @return int 修改数量
*/
int updatePwd( @Param("id") Long id, @Param("password") String password);
int deleteById(@Param("id") Long id);
List<SysUser> selectList(@Param("roleId") Integer roleId,@Param("realName") String realName);
List<SysUser> selectListByChoose(@Param("realName")String realName,@Param("roleId")Integer roleId,@Param("account")String account,@Param("createdTime") LocalDateTime createdTime);
List<SysUser> getUserByRoleIdArray(Integer[] roleIds);
List<SysUser> getUserByRoleIdList(List<Integer> roleIds);
List<SysUser> getUserByRoleIdMap(Map<String,Object> roleMap);
List<SysUser> selectPageList(@Param("realName")String realName,@Param("roleId")Integer roleId
,@Param("pageBegin")Integer pageBegin,@Param("pageSize") Integer pageSize);
}
3.mapper的xml文件
<?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接口文件路径 -->
<mapper namespace="org.example.mapper.SysUserMapper">
<resultMap id="userWithRoleName" type="SysUser">
<id column="id" property="id"/>
<result column="roleName" property="userRoleName"/>
</resultMap>
<resultMap id="userWithSysRole" type="SysUser">
<id column="id" property="id"/>
<!-- <result column="roleName" property="userRoleName"/>-->
<association property="sysRole" javaType="SysRole">
<id column="roleId" property="id"/>
<!-- <result column="roleName" property="roleName"/>-->
<!-- <result column="code" property="code"/>-->
</association>
</resultMap>
<resultMap id="userWithAddress" type="SysUser">
<id column="id" property="id"/>
<result column="account" property="account"/>
<result column="realName" property="realName"/>
<collection property="addressList" ofType="Address" resultMap="address"/>
</resultMap>
<resultMap id="address" type="Address">
<id column="addressId" property="id"/>
<result column="contact" property="contact"/>
<result column="addressDesc" property="addressDesc"/>
<result column="postCode" property="postCode"/>
<result column="tel" property="tel"/>
</resultMap>
<select id="count" resultType="int">
SELECT count(1) FROM sys_user
</select>
<select id="getUserList" resultType="SysUser">
SELECT * FROM sys_user
</select>
<select id="getUsersByRealName" resultType="SysUser">
select * from sys_user where realName like concat('%',#{name},'%')
</select>
<select id="getUserListByMap" resultType="SysUser">
select * from sys_user where 1=1
<if test="rName!=null">
and realName like concat('%',#{rName},'%')
</if>
<if test="rId!=null">
and roleId = #{rId}
</if>
</select>
<select id="getUserListByParams" resultType="SysUser">
select * from sys_user where 1=1
<if test="realName!=null">
and realName like concat('%',#{realName},'%')
</if>
<if test="roleId!=null">
and roleId = #{roleId}
</if>
</select>
<select id="getUserListWithRoleName" parameterType="SysUser" resultMap="userWithRoleName">
select u.*,r.roleName
from sys_user u
left join sys_role r on u.roleId=r.id
where 1=1
<if test="realName!=null">
and u.realName like concat('%',#{realName},'%')
</if>
<if test="roleId!=null">
and u.roleId = #{roleId}
</if>
</select>
<select id="getUserListByRoleId" resultType="org.example.entity.SysUser">
select
u.*,
r.id as roleId,
r.roleName,
r.code
from sys_user u
left join sys_role r on u.roleId=r.id
where u.roleId = #{roleId}
</select>
<resultMap id="userWithAddresses" type="SysUser">
<id column="id" property="id"/>
<result column="account" property="account"/>
<result column="realName" property="realName"/>
<!-- <collection property="addressList" ofType="Address">-->
<!-- <id column="addressId" property="id"/>-->
<!-- <result column="contact" property="contact"/>-->
<!-- <result column="addressDesc" property="addressDesc"/>-->
<!-- <result column="postCode" property="postCode"/>-->
<!-- <result column="tel" property="tel"/>-->
<!-- </collection>-->
<collection property="addressList" ofType="Address" resultMap="address"/>
</resultMap>
<select id="getUserAndAddressesByUserId" resultMap="userWithAddresses" parameterType="int">
select
u.*,
a.id as addressId,
a.contact,
a.addressDesc,
a.postCode,
a.tel
from sys_user u
left join address a on u.id=a.userId
where u.id = #{userId}
</select>
<select id="selectList" resultType="SysUser">
select * from sys_user
<!-- <where>-->
<!-- <if test="roleId!=null">-->
<!-- and roleId=#{roleId}-->
<!-- </if>-->
<!-- <if test="realName!=null and realName != ' '">-->
<!-- and realName like concat('%',#{realName},'%')-->
<!-- </if>-->
<!-- </where>-->
<trim prefix="where" prefixOverrides="and|or">
<if test="roleId!=null">
and roleId=#{roleId}
</if>
<if test="realName!=null and realName != ' '">
and realName like concat('%',#{realName},'%')
</if>
</trim>
</select>
<select id="selectListByChoose" resultType="SysUser">
select * from sys_user
<where>
<choose>
<when test="realName!=null and realName != ''">
and realName like CONCAT('%',#{realName},'%')
</when>
<when test="roleId!=null">
and roleId=#{roleId}
</when>
<when test="account!=null and account != ''">
and account like concat('%',#{account},'%')
</when>
<otherwise>
and YEAR(createdTime) = YEAR(#{createdTime})
</otherwise>
</choose>
</where>
</select>
<select id="getUserByRoleIdArray" resultType="org.example.entity.SysUser">
select * from sys_user where roleId in
<foreach collection="array" item="roleId" open="(" separator="," close=")">
#{roleId}
</foreach>
</select>
<select id="getUserByRoleIdList" resultType="org.example.entity.SysUser">
select * from sys_user where roleId in
<foreach collection="list" item="roleId" open="(" separator="," close=")">
#{roleId}
</foreach>
</select>
<select id="getUserByRoleIdMap" resultType="org.example.entity.SysUser">
select * from sys_user
<where>
roleId in
<foreach collection="roleIdList" item="roleId" open="(" separator="," close=")">
#{roleId}
</foreach>
</where>
</select>
<select id="selectPageList" resultType="org.example.entity.SysUser">
select * from sys_user
<trim prefix="where" prefixOverrides="and |or">
<if test="realName!=null">
and realName like concat('%',#{realName},'%')
</if>
<if test="roleId!=null">
and roleId=#{roleId}
</if>
</trim>
order by createdTime desc
limit #{pageBegin},#{pageSize}
</select>
<insert id="add" parameterType="SysUser">
insert into sys_user(account,realName,password,sex,birthday,phone,address,roleId,createdUserId,createdTime,updatedUserId,updatedTime)
values(#{account},#{realName},#{password},#{sex},#{birthday},#{phone},#{address},#{roleId},#{createdUserId},#{createdTime},#{updatedUserId},#{updatedTime})
</insert>
<update id="update">
update sys_user
<!-- <set>-->
<!-- <if test="account!=null">account=#{account},</if>-->
<!-- <if test="realName!=null">realName=#{realName},</if>-->
<!-- <if test="password!=null">password=#{password},</if>-->
<!-- <if test="sex!=null">sex=#{sex},</if>-->
<!-- <if test="birthday!=null">birthday=#{birthday},</if>-->
<!-- <if test="phone!=null">phone=#{phone},</if>-->
<!-- <if test="address!=null">address=#{address},</if>-->
<!-- <if test="roleId!=null">roleId=#{roleId},</if>-->
<!-- <if test="createdUserId!=null">createdUserId=#{createdUserId},</if>-->
<!-- <if test="createdTime!=null">createdTime=#{createdTime},</if>-->
<!-- <if test="updatedUserId!=null">updatedUserId=#{updatedUserId},</if>-->
<!-- <if test="updatedTime!=null">updatedTime=#{updatedTime}</if>-->
<!-- </set>-->
<!-- where id=#{id}-->
<trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
<if test="account!=null">account=#{account},</if>
<if test="realName!=null">realName=#{realName},</if>
<if test="password!=null">password=#{password},</if>
<if test="sex!=null">sex=#{sex},</if>
<if test="birthday!=null">birthday=#{birthday},</if>
<if test="phone!=null">phone=#{phone},</if>
<if test="address!=null">address=#{address},</if>
<if test="roleId!=null">roleId=#{roleId},</if>
<if test="createdUserId!=null">createdUserId=#{createdUserId},</if>
<if test="createdTime!=null">createdTime=#{createdTime},</if>
<if test="updatedUserId!=null">updatedUserId=#{updatedUserId},</if>
<if test="updatedTime!=null">updatedTime=#{updatedTime}</if>
</trim>
</update>
<update id="updatePwd">
update sys_user set password=#{password} where id=#{id}
</update>
<delete id="deleteById">
delete from sys_user where id=#{id}
</delete>
</mapper>
这只是展示大致如何使用。
3 Mybatis框架动态SQL(未完待续)
1.<if>标签
test属性:用于指定条件表达式,只有当条件为真时,才会执行该标签内的SQL片段
<select id="getUsersByCondition" parameterType="User" resultType="User">
select * from users
where 1 = 1
<if test="username!= null">
and username = #{username}
</if>
<if test="age!= null">
and age = #{age}
</if>
</select>
在这个例子中,如果传入的参数username不为null,那么就会在生成的SQL语句中添加WHERE username = #{username}这个条件。
2. <choose>、<when>、<otherwise>标签组合
test属性(<when>标签):用于指定条件表达式,只有当条件为真时,才会执行对应的SQL片段。
<otherwise>标签:表示其他情况下的默认执行。
类似于Java中的switch语句,可以根据不同的条件选择不同的SQL片段执行。例如:
<select id="getUsersByChoose" parameterType="User" resultType="User">
select * from users
where 1 = 1
<choose>
<when test="username!= null">
and username = #{username}
</when>
<when test="age!= null">
and age = #{age}
</when>
<otherwise>
and status = 'active'
</otherwise>
</choose>
</select>
这个例子中,如果username不为null,则执行and username = #{username};如果username为null但age不为null,则执行and age = #{age};如果username和age都为null,则执行and status = ‘active’。
3. <where>标签
用于自动处理where子句的条件拼接,避免多余的and或or。例如:
<select id="getUsersWithWhere" parameterType="User" resultType="User">
select * from users
<where>
<if test="username!= null">
username = #{username}
</if>
<if test="age!= null">
and age = #{age}
</if>
</where>
</select>
在这个例子中,如果传入的参数既没有username也没有指定age,那么最终生成的SQL语句中不会包含WHERE子句。
4. <set>标签
用于动态地构建UPDATE语句中的SET子句。它会自动处理多余的逗号,并在条件不满足时忽略整个SET子句。例如:
<update id="updateUser" parameterType="User">
UPDATE users
<set>
<if test="username!= null">
username = #{username},
</if>
<if test="age!= null">
age = #{age},
</if>
</set>
WHERE id = #{id}
</update>
在这个例子中,如果传入的User对象的username或age属性为null,那么在生成的UPDATE语句中就不会包含对应的设置项。
5. <foreach>标签
用于循环遍历集合或数组,并生成相应的SQL片段。
collection属性:指定要遍历的集合或数组。当参数为数组类型时,默认参数名为array。当参数为List集合时,默认参数名为list。当参数为Map中集合元素所在键值对的kay。
item属性:指定在循环中使用的集合元素的名称。
open属性:指定循环开始时添加的字符。
close属性:指定循环结束时添加的字符。
separator属性:指定循环中每个元素之间的分隔符。
例如:
<select id="getUsersByIds" parameterType="java.util.List" resultType="User">
select * from users
where id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
在这个例子中,如果传入一个包含多个用户ID的集合,标签会动态生成一个IN条件的SQL片段。
6. <trim>标签
可以自定义在SQL片段的开头和结尾添加或删除特定的字符。可以用于替代<where>和<set>标签在某些复杂场景下的使用。
prefix属性:在SQL片段的开头添加指定的字符。
suffix属性:在SQL片段的结尾添加指定的字符。
prefixOverrides属性:去除SQL片段开头的指定字符。
suffixOverrides属性:去除SQL片段结尾的指定字符。
例如:
<select id="getUsersWithTrim" resultType="User">
select * from users
<trim prefix="WHERE" suffix="" prefixOverrides="AND |OR">
<if test="username!= null">
AND username = #{username}
</if>
<if test="age!= null">
OR age = #{age}
</if>
</trim>
</select>
在这个例子中,标签会根据条件动态添加WHERE关键字,并处理开头多余的AND或OR。