在mybatis3之前,需要学习和了解非常多标签,现在采用OGNL表达式语言,消除了许多其他标签
剩下
if
choose
trim
foreach
bind
if用法:
if通常用于WHERE语句中,判断参数是否使用某个查询条件,UPDATE语句中判断是否更新某个字段,INSERT语句中判断是否插入某个字段。
在WHERE语句中使用if
需求:
实现一个用户管理高级查询功能,根据输入的条件去检索用户信息。当只输入用户时,需要根据用户名进行模糊查询,当只输入邮箱时,根据邮箱进行完全匹配;当同时输入用户名和邮箱时,用这两个条件去匹配用户。
if标签有一个必填的属性 test, test的属性是一个符合OGNL要求的判断表达式,表达式的结果为TRUE或FALSE,除此之外非0都为true,0为false。
@Test
public void testSelectByUser() {
SqlSession sqlSession = getSqlSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
SysUser sysUser = new SysUser();
sysUser.setUserName("ad");
List sysUserList = userMapper.selectByUser(sysUser);
Assert.assertTrue(sysUserList.size()>0);
// 根据邮箱查
sysUser.setUserEmail("[email protected]");
sysUser.setUserName(null);
sysUserList = userMapper.selectByUser(sysUser);
// 根据用户和邮箱查
sysUser.setUserName("ad");
Assert.assertTrue(sysUserList.size()==0);
} finally {
sqlSession.close();
}
}
if 用法,加一个
中间加 and 条件。
if中符合条件才会有and条件。
在update中使用if
需求:
只更新变化的字段。需要注意,更新的时候不能将原来有值但没发生变化的字段更新为空或者NULL。
通过IF就可以实现这种动态更新
示例:
UPDATE sys_user
SET
user_name = #{userName},
user_password = #{userPassword},
user_email = #{userEmail},
user_info = #{userInfo},
head_img = #{headImg, jdbcType=BLOB},
create_time = #{createTime, jdbcType=TIMESTAMP},
id = #{id}
WHERE id = #{id}
测试:
@Test
public void testUpdateByIdSelective() {
SqlSession sqlSession = getSqlSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
SysUser sysUser = userMapper.selectById(1l);
sysUser.setUserName("cccc");
userMapper.updateByIdSelective(sysUser);
} finally {
sqlSession.rollback();
sqlSession.close();
}
}
在insert中使用if
应用场景:
在数据表中插入参数是,如果参数值不为空,就传入,如果传入值为空,就使用数据库中默认的值,而不使用空值。
示例:
insert INTO sys_user(
user_name, user_password,
user_email,
user_info, head_img, create_time
)
VALUES (
#{userName}, #{userPassword},
#{userEmail},
#{userInfo}, #{headImg, jdbcType= BLOB}, #{createTime, jdbcType= DATE}
)
choose用法
可以实现if ...else...的逻辑
案例需求:
当参数id有值的时候,优先使用id查询,当id没有值的时候,便去判断用户名是否有值,如果有值就用用户名查询,如果没有值,就使SQL查询无结果。
方案:
测试代码:
@Test
public void testselectByIdOrUserName() {
SqlSession sqlSession = getSqlSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
SysUser sysUser = userMapper.selectById(1l);
sysUser.setId(null);
SysUser sysUser1 = userMapper.selectByIdOrUserName(sysUser);
sysUser.setUserName(null);
sysUser1 = userMapper.selectByIdOrUserName(sysUser);
} finally {
sqlSession.close();
}
}
where/set/trim用法:
where标签的用法:如果标签包含的元素中有返回值,就插入一个where,如果where后面的字符串是以and和or开头的,就将它们剔除。
where会自动剔除 and 或 or 开头的 and 和 or
set的用法:
如果标签包含元素中的返回值,就插入一个set,如果set后面中的元素是以逗号结尾的,就将这个逗号剔除。
但是如果set元素中没有内容,照样会出现SQL错误,所以,类似id = #{id}这样必然存在的赋值任然需要保留。
例子:
UPDATE sys_user
user_name = #{userName},
user_password = #{userPassword},
user_email = #{userEmail},
user_info = #{userInfo},
head_img = #{headImg, jdbcType=BLOB},
create_time = #{createTime, jdbcType=TIMESTAMP},
id = #{id},
WHERE id = #{id}
trim用法:
where和set都是通过trim实现,并且底层都是通过TrimSqlNode实现的。
...
...
foreach用法
SQL语句中有时会使用IN关键字,例如 id in (1, 2, 3),可以使用$(ids)方式直接获取值,但是不能放置SQL注入,避免SQL注入就需要使用#{}的方式,这是就要配合使用foreach标签来满足需求。
foreach可以对数组、Map或实现Iterable接口的对象进行遍历
foreach实现in集合
案例需求:
根据用户ID集合查询出所有符合条件的用户
实现:
foreach包含以下属性:
collection:必填,值为要迭代循环的属性名。这个属性值的情况很多。
item:变量名,值为从迭代对象中取出的每一个值。
index:索引的属性名,在集合数组情况下值为当前索引值,当迭代对象是Map类型是,这个值为KEY。
open、close、separator。
foreach实现批量插入:
如果数据库支持批量插入,就可以通过foreach来实现。批量插入是SQL-92新增的特性,目前支持的数据库有DB2、SQL Server8.2及其以上版本、Mysql、Sqlite3.7.11以上、H2。
批量插入语法如下:
INSERT INTO tablename (colum-a, [colum-b, ....])
VALUES('value-1a', ['value-1b', ...]),
('value-2a', ['value-2b', ...]),
....
例子:
INSERT INTO sys_user(
user_name, user_password, user_email, user_info, head_img, create_time
)
VALUES
(
#{user.userName}, #{user.userPassword}, #{user.userEmail}, #{user.userInfo}, #{user.headImg, jdbcType= BLOB},
#{user.createTime, jdbcType= DATE}
)
测试代码:
@Test
public void testInsertList() {
SqlSession sqlSession = getSqlSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List sysUserList = new ArrayList();
for (int i = 0; i < 2; i++) {
SysUser sysUser = new SysUser();
sysUser.setUserName("cc");
sysUser.setUserPassword("111111");
sysUser.setUserEmail("[email protected]");
sysUserList.add(sysUser);
}
int result = userMapper.insertList(sysUserList);
for (SysUser s :
sysUserList) {
System.out.println(s.getId());
}
Assert.assertEquals(2, result);
} finally {
//为了不影响其他测试,这里选择回滚
sqlSession.rollback();
sqlSession.close();
}
}
这里使用了useGeneratedKeys 和 keyProperty 两个属性,可以实现批量插入后返回主键。
foreach实现动态update
这个主要介绍参数是Map时,foreach怎么实现动态update。
bind标签,创建一个变量并将其绑定到上下文中。