MyBatis 框架学习(II)
文章目录
- MyBatis 框架学习(II)
- 1. 介绍
- 2. 准备&测试
- 2.1 配置数据库连接字符串和MyBatis
- 2.2 编写持久层代码
- 3. MyBatis XML基础操作
- 3.1 Insert 操作
- 3.2 Delete 操作
- 3.3 Update 操作
- 3.4 Select 操作
- 4. #{} 与 ${}的使用
- 5. 动态SQL操作
- 5.1 < if >标签
- 5.2 < trim >标签
- 5.3 < where >标签
- 5.4 < set >标签
- 5.5 < foreach >标签
- 5.6 < include >标签
- 总结
在上一篇文章中,我们学习了通过
注解
的方式(
MyBatis 框架学习(I) )来进行
MyBatis开发,接下来我们来学习使用
XML
的方式进行
MyBatis开发:
1. 介绍
使用MyBatis注解的方式主要是用来解决简单的SQL操作,如增删改查功能,如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中
2. 准备&测试
想要进行XML的使用,我们需要先完成以下配置:
- 配置数据库连接字符串和MyBatis;
- 编写持久层代码
2.1 配置数据库连接字符串和MyBatis
如果配置文件是application.properties
,代码如下:
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_test
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456
#配置mybatis的日志, 指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启mybatis的驼峰命名自动映射开关 a_column ------> aCloumn
mybatis.configuration.map-underscore-to-camel-case=true
# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件 --> 使用XML需要配置这个
mybatis.mapper-locations=classpath:mapper/**Mapper.xml
如果配置文件是application.yml
,代码如下:
# 数据库连接配置 每个空格都不能省略,yml严格要求格式正确
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置打印 MyBatis⽇志
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mybatis:
configuration:
map-underscore-to-camel-case: true #配置驼峰⾃动转换
# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis:
mapper-locations: classpath:mapper/**Mapper.xml
2.2 编写持久层代码
持久层代码分两部分:
- 方法定义:Interface
- 方法实现:XXX.xml
首先需要定义mapper接口:
@Mapper
public interface UserInfoXmlMapper {
// 查询所有用户
public List<UserInfo> queryAllUser();
}
之后创建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.example.blog_mybatis.mapper.UserInfoXmlMapper">
<select id="queryAllUser" resultType="org.example.blog_mybatis.pojo.UserInfo">
select username, password, id, username,
password, age, gender, phone, delete_flag,
create_time, update_time from userinfo
</select>
</mapper>
对上述内容进行分析:
-
<mapper>
标签:需要指定namespace
属性,表示命名空间,值为mapper接口的全限定名称,即包括全包名.类名
,可以通过以下方式直接获取: -
< select >
标签:查询标签,用于进行数据库中的查询操作:id
:是和mapper接口中定义的方法名称一致,表示对接口的具体实现方法;resultType
:返回的数据类型,也就是我们定义的实体类(也需要为全限定名称)
最后编写测试代码:
package org.example.blog_mybatis.mapper;
import org.example.blog_mybatis.pojo.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class UserInfoXmlMapperTest {
@Autowired
private UserInfoXmlMapper userInfoXmlMapper;
@Test
void queryAllUser() {
List<UserInfo> list = userInfoXmlMapper.queryAllUser();
System.out.println(list);
}
}
测试成功!!
3. MyBatis XML基础操作
3.1 Insert 操作
在UserInfoXmlMapper
中进行方法定义:
Integer InsertUser(UserInfo userInfo);
之后在XML文件
中进行方法实现:
<insert id="InsertUser">
insert into userinfo(username, password, age, phone, gender)
values (#{username}, #{password}, #{age}, #{phone}, #{gender})
</insert>
编写测试方法:
@Test
void insertUser() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("飞天虎");
userInfo.setPassword("125");
userInfo.setAge(38);
userInfo.setGender(1);
userInfo.setPhone("100");
Integer count = userInfoXmlMapper.InsertUser(userInfo);
System.out.println("添加数据条数:" + count);
}
如果使用@Param设置参数名称的话,使用方法和注解类似,同时若需要获取ID,可以在insert标签中添加属性useGeneratedKeys
和keyProperty
:
<insert id="InsertUser" useGeneratedKeys="true" keyProperty="id" >
insert into userinfo(username, password, age, phone, gender)
values (#{username}, #{password}, #{age}, #{phone}, #{gender})
</insert>
3.2 Delete 操作
在UserInfoXmlMapper
中进行方法定义:
void DeleteUser(Integer id);
之后在XML文件
中进行方法实现:
<delete id="DeleteUser">
delete from userinfo where id = #{id}
</delete>
编写测试方法:
@Test
void deleteUser() {
userInfoXmlMapper.DeleteUser(14);
}
3.3 Update 操作
在UserInfoXmlMapper
中进行方法定义:
Integer UpdateUser(UserInfo userInfo);
之后在XML文件
中进行方法实现:
<update id="UpdateUser">
update userinfo set username = #{username}, age = #{age} where id = #{id}
</update>
编写测试方法:
@Test
void updateUser() {
UserInfo userInfo = new UserInfo();
userInfo.setId(12);
userInfo.setUsername("张三丰");
userInfo.setAge(100);
Integer count = userInfoXmlMapper.UpdateUser(userInfo);
System.out.println("修改数据:" + count);
}
3.4 Select 操作
在UserInfoXmlMapper
中进行方法定义:
UserInfo queryUser(Integer id);
之后在XML文件
中进行方法实现:
<select id="queryUser" resultType="org.example.blog_mybatis.pojo.UserInfo">
select id, username, password, age,
gender, phone, delete_flag,
create_time, update_time from userinfo where id = #{id}
</select>
编写测试方法:
@Test
void queryUser() {
UserInfo userInfo = userInfoXmlMapper.queryUser(5);
System.out.println(userInfo);
}
注:这里能够正确的获取到全部数据是因为在配置文件里配置了自动进行驼峰命名,若没有添加这个配置则返回结果中后续几个属性值(deleteFlag开始)会为null,如何添加在上篇文章有介绍:[MyBaits 框架学习(I)]
4. #{} 与 ${}的使用
在前面我们使用#{}
来进行参数传递,#{}
本身属于预编译SQL机制,通过?
占位的方式提前对SQL进行编译,然后把参数填充到SQL语句中,如下:
如果传进来的是String类型的参数,#{}
也会根据类型自动添加引号
而${}
是即时SQL,它的作用就是将参数直接拼接到SQL语句中:
如果传入的参数是字符串的话,需要手动给它添加上引号,否则传入${}
的参数不会自动添加引号,进而报错,比如通过名称查询用户信息,若xml代码这样写:
<select id="queryUserByName" resultType="org.example.blog_mybatis.pojo.UserInfo">
select id, username, password, age,
gender, phone, delete_flag,
create_time, update_time from userinfo where username = ${username}
</select>
可以看到运行结果会报错,此时就需要我们手动给${}
添加引号:
<select id="queryUserByName" resultType="org.example.blog_mybatis.pojo.UserInfo">
select id, username, password, age,
gender, phone, delete_flag,
create_time, update_time from userinfo where username = '${username}'
</select>
此时查询结果就正确了
5. 动态SQL操作
MyBatis为我们提供了一个强大的功能来解决复杂的SQL操作,那就是动态SQL,它能够完成不同条件下不同的sql拼接,接下来我们来学习相应的标签:
5.1 < if >标签
当我们需要根据特定条件进行语句判断时即可以使用if标签
,比如之前通过Insert操作向数据库插入用户信息:
<insert id="InsertUser" useGeneratedKeys="true" keyProperty="id" >
insert into userinfo(username, password, age, phone, gender)
values (#{username}, #{password}, #{age}, #{phone}, #{gender})
</insert>
如果这个时候性别是非必填字段,希望根据用户有无传入这个属性来让sql编译时自动添加gender这个字段,则可以使用if标签来进行判断:
<insert id="InsertUser" useGeneratedKeys="true" keyProperty="id" >
insert into userinfo(
username,
password,
age,
phone,
<if test="gender != null">
gender
</if>
)
values (#{username},
#{password},
#{age},
#{phone},
<if test="gender != null">
#{gender}
</if>
)
</insert>
此时因为没有传入gender参数所以sql语句编译时没有显示gender字段
5.2 < trim >标签
在上面的if语句中,其实存在着一个隐藏的问题,那就是字段后面的逗号(","
),如果我的gender属性为null,则上述phone字段后面跟着的逗号也会一起被sql语句编译,这个时候就会出现问题了:
这个时候我们可以通过trim标签来解决这个问题:
insert into userinfo(
<trim suffixOverrides=",">username,
password,
age,
phone,
<if test="
gender != null">
gender
</if>
</trim>
)
values (
<trim suffixOverrides=",">
#{username},
#{password},
#{age},
#{phone},
<if test="gender != null">
#{gender}
</if>
</trim>
)
</insert>
对于trim标签
,它有以下属性:
- prefix:表示整个语句块(从<trim>到</trim>),以prefix的值为前缀;
- suffix:表示整个语句块,以suffix的值为后缀;
- prefixOverrides:表示整个语句块要除掉的前缀;
- suffixOverrides:表示整个语句块要除掉的后缀,比如上述代码中的
","
在一般情况下,当我们需要对多个字段进行动态生成时即可使用trim标签
5.3 < where >标签
<where
>标签只会在子元素有内容的情况下才会插入where子句,而且会自动去除子句开头的 AND
或 OR
:
先在UserInfoXmlMapper
中进行方法定义:
List<UserInfo> queryUserByCondition(Integer age, Integer gender, Integer deleteFlag);
之后在XML文件
中进行方法实现:
<select id="queryUserByCondition" resultType="org.example.blog_mybatis.pojo.UserInfo">
select username, password, id, username,
password, age, gender, phone, delete_flag,
create_time, update_time from userinfo
<where>
<if test="age != null">
and age = #{age}
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="deleteFlag != null">
and delete_flag = #{deleteFlag}
</if>
</where>
</select>
编写测试方法:
@Test
void queryUserByCondition() {
List<UserInfo> list = userInfoXmlMapper.queryUserByCondition(18, 1,0);
System.out.println(list);
}
注:test属性对应的参数为方法传入参数而不是字段名,且如果方法传入参数为空,where标签中子元素无内容,不会插入子句:
5.4 < set >标签
当我们需要根据用户传入的信息来修改内容时,可以通过set标签
实现动态修改,如修改参数不为null的属性:
<update id="UpdateUser">
update userinfo
<set>
<if test="username != null">
username = #{username}
</if>
<if test="age != null">
age = #{age},
</if>
<if test="deleteFlag != null">
delete_flag = #{deleteFlag}
</if>
</set>
where id = #{id}
</update>
set标签
用于update语句
中,并且会删除额外的逗号,以上标签也可以使用替换
5.5 < foreach >标签
当我们需要对集合进行遍历时可以使用该标签,foreach标签
有以下属性:
- collection:绑定方法参数中的集合,如List,Set,Map或数组对象;
- item:遍历时的每一个对象;
- open:遍历开始时加的前缀;
- close:遍历结束时加的后缀;
- separator:每次遍历之间间隔的字符串
如果我们现在需要批量删除用户信息,就可以使用foreach标签
进行遍历删除,代码如下:
在UserInfoXmlMapper
中进行方法定义:
void DeleteUserById(List<Integer> ids);
之后在XML文件
中进行方法实现:
<delete id="DeleteUserById">
delete from userinfo
<where>
id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</where>
</delete>
编写测试代码:
void deleteUserById() {
List<Integer> list = new ArrayList<>();
list.add(15);
list.add(16);
list.add(17);
userInfoXmlMapper.DeleteUserById(list);
}
5.6 < include >标签
在XMl文件中配置sql,有时候会出现许多重复的字段,这样会造成一定的代码冗余:
对此,我们可以对重复的代码进行抽取,将其通过<sql>标签
封装到一个SQL片段中,然后再通过<include>标签
进行引用:
- <sql>:定义可重复的SQL片段;
- <include>:通过属性refid,指定包含的SQL片段
在xml文件中添加:
<sql id="allColum">
id, username, password, age,
gender, phone, delete_flag,
create_time, update_time
</sql>
通过标签引用重复sql片段,且rafid属性的值与sql标签中id的属性值相同:
<select id="queryUser" resultType="org.example.blog_mybatis.pojo.UserInfo">
select <include refid="allColum"></include> from userinfo where id = #{id}
</select>
总结
对于MyBatis XML方式的使用就介绍到这,对于注解和XML两者的使用范围并不固定,推荐在进行简单的SQL操作时可以使用注解更加方便快捷,而对于复杂的SQL操作则可以使用XML的方式来进行高效解决!!