foreach标签
需求:
select * from sys_user where id in (1,2,3);
这样的sql在mybatis中如何实现??
1. foreach实现批量插入
语法如下:
insert into table_name (col_1,col2,...)values('value-1a',['value-1b',..]),('value-2a',['value-2b,...']),...
从待处理的部分可以看出,后面时一个值的循环,可以通过foreach实现循环插入。
重新建表 emp:
CREATE TABLE `emp` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`user_name` VARCHAR(50) DEFAULT NULL COMMENT '用户名',
`user_password` VARCHAR(50) DEFAULT NULL COMMENT '密码',
`user_email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
`user_info` TEXT COMMENT '简介',
`head_img` BLOB COMMENT '头像',
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表';
实体类Emp:
/**
* @author snow
*/
public class Emp {
/**
* 用户ID
*/
private Long id;
/**
* 用户名
*/
private String userName;
/**
* 用户密码
*/
private String userPassword;
/**
* 用户邮箱
*/
private String userEmail;
/**
* 简介
*/
private String userInfo;
/**
* 头像
*/
private Byte[] headImg;
/**
* 创建时间
*/
private Date createTime;
//省去get和set方法
}
创建EmpMapper.java,并添加如下方法:
public interface EmpMapper {
/**
* 批量插入用户信息
* @param emps
* @return
*/
int insertList(List<Emp> emps);
}
创建EmpMapper.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="tk.mybatis.simple.mapper.EmpMapper">
<!--
useGeneratedKeys:返回插入记录的自增主键
keyProperty:指定属性为id
-->
<insert id="insertList" useGeneratedKeys="true" keyProperty="id">
INSERT INTO emp
(user_name,user_password,user_email,user_info,head_img,create_time)
values
<foreach collection="list" item="emp" separator=",">
(#{emp.userName},#{emp.userPassword},#{emp.userEmail},
#{emp.userInfo},#{emp.headImg,jdbcType=BLOB},
#{emp.createTime,jdbcType=TIMESTAMP})
</foreach>
</insert>
</mapper>
foreach标签属性的说明:
foreach元素的属性主要有 item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名,
index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,
open表示该语句以什么开始,
separator表示在每次进行迭代之间以什么符号作为分隔符,
close表示以什么结束。
测试代码如下:
public class EmpMapperTest extends BaseMapperTest{
@Test
public void testInsertList(){
SqlSession sqlSession = getSqlSession();
try {
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> emps = new ArrayList();
for(int i=1;i<=5;i++){
Emp emp = new Emp();
emp.setUserName("test "+i);
emp.setUserPassword("123456");
emp.setUserInfo("info "+i);
emp.setUserEmail("email "+i);
emp.setCreateTime(new Date());
emps.add(emp);
}
int i = empMapper.insertList(emps);
System.out.println(i);
for(Emp e : emps){
System.out.println(e.getId());
}
}finally {
sqlSession.commit();
sqlSession.close();
}
}
}
测试结果如下:
[DEBUG] 2018-04-29 13:33:32,795 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Preparing: INSERT INTO emp (user_name,user_password,user_email,user_info,head_img,create_time) values (?,?,?, ?,?, ?) , (?,?,?, ?,?, ?) , (?,?,?, ?,?, ?) , (?,?,?, ?,?, ?) , (?,?,?, ?,?, ?)
[DEBUG] 2018-04-29 13:33:32,835 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters: test 1(String), 123456(String), email 1(String), info 1(String), null, 2018-04-29 13:33:32.708(Timestamp), test 2(String), 123456(String), email 2(String), info 2(String), null, 2018-04-29 13:33:32.708(Timestamp), test 3(String), 123456(String), email 3(String), info 3(String), null, 2018-04-29 13:33:32.708(Timestamp), test 4(String), 123456(String), email 4(String), info 4(String), null, 2018-04-29 13:33:32.708(Timestamp), test 5(String), 123456(String), email 5(String), info 5(String), null, 2018-04-29 13:33:32.708(Timestamp)
[DEBUG] 2018-04-29 13:33:32,924 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Updates: 5
5
1
2
3
4
5
测试结果将主键值也返回了。。。
2. foreach实现in集合
在EmpMapper.java中添加如下代码
/**
* 根据用户id集合查询
* @param idList
* @return
*/
List<Emp> selectByIdList(@Param("idList") List<Long> idList);
对应的xml配置如下:
<select id="selectByIdList" resultType="tk.mybatis.simple.model.Emp">
SELECT * from emp
<where>
id in
<foreach collection="idList" separator="," open="(" close=")"
index="i" item="id">
#{id}
</foreach>
</where>
</select>
测试代码略去…
如果参数传递的是数组,则代码修改如下:
/**
* 根据用户id集合查询
* @param idArray
* @return
*/
List<Emp> selectByIdList(Long[] idArray);
xml配置如下:
<select id="selectByIdList" resultType="tk.mybatis.simple.model.Emp">
SELECT * from emp
<where>
id in
<foreach collection="array" separator="," open="(" close=")"
index="i" item="id">
#{id}
</foreach>
</where>
</select>
3. foreach实现动态update
在EmpMapper.java中添加如下代码:
/**
* 通过Map更新列
* @param maps
* @return
*/
int updateByMap(Map<String,Object> maps);
对应的xml的配置
<!--
这里使用key作为列名,对应的值作为该列的值,
通过foreach将需要更新的字段拼接在SQL语句中
由于java代码中没有使用@param注解,mybatis在内部的上下文中使用了默认值
_parameter作为该参数的key,所以在xml文件中使用_parameter
-->
<update id="updateByMap">
UPDATE emp
SET
<foreach collection="_parameter" item="val" index="key" separator=",">
${key} = #{val}
</foreach>
where id = #{id}
</update>
测试代码如下:
@Test
public void testUpdateByMap(){
SqlSession sqlSession = getSqlSession();
try {
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
Map<String,Object> maps = new HashMap<>();
maps.put("id",1L);
maps.put("user_password","qwwdwedawedaw");
int i = empMapper.updateByMap(maps);
System.out.println(i);
}finally {
sqlSession.commit();
sqlSession.close();
}
}
————————————————————————————————————————————————————
其他的一些标签
- bind标签可以使用 OGNL 表达式创建一个变量井将其绑定到上下文中
<if test="userName != null and userName != ''">
AND user_name like '%'||#{userName}||'%'
</if>
可以修改为如下
<if test="userName != null and userName != ''">
<bind name="userNameLike" value="'%'+userName}+'%'"/>
AND user_name like #{userNameLike}
</if>
多数据库的支持:
在mybatis-config.xml中加入如下配置,
<!--多数据库的支持-->
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
</databaseIdProvider>
修改selectByUser的代码如下:(可以避免切换数据库带来的麻烦。)
<select id="selectByUser" resultType="tk.mybatis.simple.model.SysUser">
SELECT id,
user_name userName,
user_password userPassword,
user_email userEmai,
user_info userInfo,
head_Img headImg,
create_time createTime
FROM sys_user
<where>
<if test="userName != null and userName != ''">
<if test="_databaseId=='mysql'">
AND user_name like concat('%',#{userName},'%')
</if>
<if test="_databaseId=='oracle'">
AND user_name like '%'||#{userName}||'%'
</if>
</if>
<if test="userEmail != null and userEmail != ''">
AND user_email = #{userEmail}
</if>
</where>
</select>
OGNL表达式
e1 or e2
e1 and e2
e1 == e2,e1 eq e2
e1 != e2,e1 neq e2
e1 lt e2:小于
e1 lte e2:小于等于,其他gt(大于),gte(大于等于)
e1 in e2
e1 not in e2
e1 + e2,e1 * e2,e1/e2,e1 - e2,e1%e2
!e,not e:非,求反
e.method(args)调用对象方法
e.property对象属性值
e1[ e2 ]按索引取值,List,数组和Map
@class@method(args)调用类的静态方法
@class@field调用类的静态字段值
定义一个工具类 tk.mybatis.util.StringUtil.java,代码如下:
/**
* @author snow
*/
public class StringUtil {
public static boolean isEmpty(String userName){
return userName == null || userName.length() == 0;
}
public static boolean isNotEmpty(String userName){
return !isEmpty(userName);
}
}
则:
<if test="userName != null and userName != ''"></if>
可以修改为如下代码:
<if test="@tk.mybatis.util.StringUtil@isNotEmpty(userName)">
</if>