MyBatis 中的动态 SQL 就是SQL语句可以根据不同的情况情况来拼接不同的sql。
本文会介绍 xml 和 注解 两种方式的动态SQL实现方式。
先创建一个数据表,SQL代码如下:
DROP TABLE IF EXISTS `userinfo`; CREATE TABLE `userinfo` ( `id` int(11) NULL DEFAULT NULL, `username` varchar(127) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `gender` tinyint(4) NULL DEFAULT NULL COMMENT '1-男 2-⼥ ', `delete_flag` tinyint(4) NULL DEFAULT 0 COMMENT '0-正常, 1-删除', `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP, `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
数据库表和JAVA对象的对应如下:
平时在注册账号时会有一些非必填项,而我们就可以使用
接口定义:
@Mapper public interface Userinfo { Integer addUserinfo(User user); }
语法:
如果 test 后面的条件判断结果为 true,那么就将后面的语句块拼接到最终的 SQL 语句中。
XML的实现代码如下:
insert into userinfo(id, username, gender, delete_flag ) values ( #{id},#{username},#{gender}, #{deleteFlag} );
注意:test中的gender和deleteFlag,是传入对象中的属性,不是数据库字段。
执行以下测试代码:
@Test void addUserinfo() { User user = new User(); user.setId(2); user.setUsername("zhangsan"); user.setDeleteFlag(0); //此时gender为空 userinfo.addUserinfo(user); }
运行之后我们从日志中可以看出最终执行的SQL语句中并没有 gender
而当我们令gender不为空:
user.setGender(1);
但是此时我们的代码还有一个隐藏BUG,比如当deleteFlag为空时:
@Test void addUserinfo() { User user = new User(); user.setId(2); user.setUsername("zhangsan"); //user.setDeleteFlag(0); user.setGender(1); //此时deleteFlag为空 userinfo.addUserinfo(user); }
此时代码报错了,我们可以从MyBatis打印的日志中看出SQL语句出现了多余的逗号。
此时就需要使用
我们利用
insert into userinfo id, username, valuesgender, delete_flag #{id},#{username}, #{gender}, #{deleteFlag}
此时程序就可以正常执行了。
OR。
例如:我们此时根据 id 和 gender 来查找数据。
数据库中的数据如下:
接口定义:
User selectUser(Integer id, Integer gender);
xml实现:
JAVA测试代码
@Test void selectUser() { System.out.println(userinfo.selectUser(1, 1)); }
从打印的结果和日志中我们可以看出结果正确。
如果 id 和 gender 都为 null
@Test void selectUser() { System.out.println(userinfo.selectUser(null, null)); }
虽然程序报错了,可是并不是因为SQL错了而是因为接收的参数报错。
此时可以看出 where 被去掉了。
此时如果 gender 为空
@Test void selectUser() { System.out.println(userinfo.selectUser(1, null)); }
用于 update 语句中动态的在SQL语句中插入 set 关键字,并会删掉额外的逗号。
例如:根据传入的id属性,修改 username 和 gender 中不为null的属性。
接口定义:
Integer upData(Integer id, String username, Integer gender);
xml代码实现:
update userinfo where id = #{id}; username = #{username}, gender = #{gender}
JAVA测试代码
void upData() { //gender为空 userinfo.upData(2, "xiaohong", null); }
可以看出删掉了额外的逗号(前后都会删掉)。
该标签可以在对集合进行遍历时使用。
标签有如下属性:
例如:批量删除数据
接口定义:
Integer deleteUsers(Listids);
xml代码实现:
delete from userinfo where id in #{id}
注意:这两个地方的名称必须相同。
JAVA测试代码
@Test void deleteUsers() { Listlist = new ArrayList<>(); list.add(1); list.add(2); userinfo.deleteUsers(list); }
这两个标签配合使用可以实现对重复的代码片段进行抽取,将其通过
例如:我们可以抽取下面xml中的部分代码。
delete from userinfo where id in #{id}
delete from userinfo where id in #{id}
JAVA测试代码
@Test void deleteUsers() { Listlist = new ArrayList<>(); list.add(1); list.add(2); userinfo.deleteUsers(list); }
注解的实现其实非常简单只需把xml标签中的SQL(包括标签),使用 标签括起来就可以了。
例如下面的xml代码
INSERT INTO userinfo ( username, `password`, age, gender, phone) VALUES ( #{username}, #{age},#{gender}, #{phone})
注解的实现方法:
@Insert("") Integer insertUserByCondition(UserInfo userInfo);