目录:
一 、实验目的:
通过 mybatis 提供的各种标签方法实现动态拼接 sql
二 、预习要求:
预习 if、choose、 when、where 等标签的用法
三、实验内容:
- 根据性别和名字查询用户
- 使用 if 标签改造 UserMapper.xml
- 使用 where 标签进行改造 UserMapper.xml
- 使用 Sql 片段改造 UserMapper.xml
- 利用 foreach 标签实现根据多个 id 查询用户信息
四、实验方法和步骤:
实验前准备:
①创建数据库experience03,创建表user,并插入以下数据:
CREATE DATABASE experience03;
USE experience03;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`birthday` date NULL DEFAULT NULL,
`sex` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`address` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ;
INSERT INTO `user` VALUES (1, '关羽', '2024-09-29', '男', '蜀国');
INSERT INTO `user` VALUES (2, '梁王孙', '2024-09-11', '男', '北京市');
INSERT INTO `user` VALUES (3, '陈长生', '2024-05-14', '女', '京都西庙');
INSERT INTO `user` VALUES (4, '王婆', '2024-09-05', '女', '快远');
INSERT INTO `user` VALUES (5, '黄忠', '2016-07-24', '1', '三国');
INSERT INTO `user` VALUES (6, '张飞', '2024-10-16', '女', '三国');
INSERT INTO `user` VALUES (7, 'lucky', '2021-10-08', '男', '三国');
INSERT INTO `user` VALUES (14, '关羽', '2024-12-02', '男', '蜀国');
②配置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>com.haust</groupId>
<artifactId>experience03</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.14</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
</dependencies>
</project>
③编写User.java在com.haust.pojo中
package com.haust.pojo;
import java.util.Date;
public class User {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
在java/com/haust/mapper中创建UserMapper接口
package com.mapper;
public interface UserMapper {
}
在resources/com/haust/mapper简历UserMapper.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="">
</mapper>
在resources下创建db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/experience03
jdbc.username=root
jdbc.password=root
在resources根目录下配置mybatis-config.cml
<?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 resource="db.properties"/>
<!-- <settings>-->
<!-- <setting name="logImpl" value="LOG4J"/>-->
<!-- </settings>-->
<typeAliases>
<typeAlias type="com.haust.pojo.User" alias="User"/>
</typeAliases>
<environments default="environment">
<environment id="environment">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/haust/mapper/UserMapper.xml"/>
</mappers>
</configuration>
(1)根据性别和名字查询用户
查询 sql:
SELECT id, username, birthday, sex, address
FROM `user`
where sex = '1' AND username LIKE '%张%'
①Mapper.xml 文件
UserMapper.xml 配置 sql,如下:
<select id="findUserUsernameAndSex" parameterType="com.haust.pojo.User" resultType="com.haust.pojo.User">
select * from user
where username like '%${username}%' and sex = #{sex}
</select>
②Mapper 接口
编写 Mapper 接口,如下:
List<User> findUserUsernameAndSex(User user);
③测试方法
在 UserMapperTest 添加测试方法,如下:
@Test
public void test09() throws IOException {
String resources = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resources);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setSex("女");
user.setUsername("王");
List<User> list = userMapper.findUserUsernameAndSex(user);
System.out.println(list);
sqlSession.commit();
sqlSession.close();
}
④实验效果
测试效果如下图:
如果注释掉 user.setSex("1"),测试结果如下图:
测试结果二很显然不合理。
按照之前所学的,要解决这个问题,需要编写多个 sql,查询条件越多,需要编写的 sql 就 更多了,显然这样是不靠谱的。
解决方案,使用动态 sql 的 if 标签
(2)使用 if 标签改造 UserMapper.xml
(二)使用 if 标签改造 UserMapper.xml
①改造 UserMapper.xml,如下:
<select id="findUserUsernameAndSex" parameterType="com.haust.pojo.User" resultType="com.haust.pojo.User">
select * from user
where 1=1
<if test="username != null and username != ''">
and username like '%${username}%'
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</select>
注意字符串类型的数据需要要做不等于空字符串校验。
②实验效果
测试类:
@Test
public void test09() throws IOException {
String resources = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resources);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
// user.setSex("男");
user.setUsername("王");
List<User> list = userMapper.findUserUsernameAndSex(user);
System.out.println(list);
sqlSession.commit();
sqlSession.close();
}
如上图所示,测试 OK
注意:使用<if test="">后sex注释掉,会选择username作为唯一条件
(3)使用 where 标签进行改造 UserMapper.xml
(三)使用 where 标签进行改造 UserMapper.xml
上面的 sql 还有 where 1=1 这样的语句,很麻烦
可以使用 where 标签进行改造,where 标签可以自动添加 where,同时处理 sql 语句中第一个 and 关键字
①改造 UserMapper.xml,如下
<select id="findUserUsernameAndSex" parameterType="com.haust.pojo.User" resultType="com.haust.pojo.User">
select * from user
<where>
<if test="username != null and username != ''">
and username like '%${username}%'
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</where>
</select>
测试类:
@Test
public void test09() throws IOException {
String resources = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resources);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
// user.setSex("男");
user.setUsername("王");
List<User> list = userMapper.findUserUsernameAndSex(user);
System.out.println(list);
sqlSession.commit();
sqlSession.close();
}
②实验效果
(4)使用 Sql 片段改造 UserMapper.xml
使用 Sql 片段改造 UserMapper.xml Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。
①把上面例子中的 id, username, birthday, sex, address 提取出来,作为 sql 片段,如下:
<select id="findUserUsernameAndSex" parameterType="com.haust.pojo.User" resultType="com.haust.pojo.User">
select <include refid="userFields"></include> from user
<where>
<if test="username != null and username != ''">
and username like '%${username}%'
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</where>
</select>
<sql id="userFields">
id, username, birthday, address, sex
</sql>
如果要使用别的 Mapper.xml 配置的 sql 片段,可以在 refid 前面加上对应的 Mapper.xml 的
namespace。
(5)利用 foreach 标签实现根据多个 id 查询用户信息
利用 foreach 标签实现根据多个 id 查询用户信息
向 sql 传递数组或 List,mybatis 使用 foreach 解析,如下:
①根据多个 id 查询用户信息
查询 sql:
SELECT * FROM user WHERE id IN (1,3,4)
①在java/com/haust/pojo下创建 QueryVo
如下在 pojo 中定义 list 属性 ids 存储多个用户 id,并添加 getter/setter 方法
package com.haust.pojo;
import java.util.List;
public class QueryVo {
private User user;
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "QueryVo{" +
"user=" + user +
", ids=" + ids +
'}';
}
}
②Mapper.xml 文件
UserMapper.xml 添加 sql,如下:
<select id="findUserByList" parameterType="com.haust.pojo.QueryVo" resultType="com.haust.pojo.User">
select * from user where id in
<foreach collection="list" item="id" index="index" separator="," open="(" close=")">
#{id}
</foreach>
</select>
③测试方法如下图:
@Test
public void test10() throws IOException {
String resources = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resources);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
QueryVo queryVo = new QueryVo();
List<Integer> list = new ArrayList();
list.add(1);
list.add(3);
list.add(4);
List<User> list1 = userMapper.findUserByList(list);
for (User u:list1){
System.out.println(u);
}
sqlSession.commit();
sqlSession.close();
}
④实验效果
测试效果如下图: