说明:方便后续根据场景直接拷贝代码
@[toc]
一、foreach 标签的属性含义
foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。
foreach元素的属性主要有 item,index,collection,open,separator,close。
item集合中每一个元素进行迭代时的别名,
index表示在迭代过程中,每次迭代到的位置,
open该语句以什么开始,
separator在每次进行迭代之间以什么符号作为分隔 符,
close以什么结束,
在使用foreach的时候最关键的也是最容易出错的就是collection属性,
该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,
主要有一下3种情况:
- 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
- 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了
二、使用注意事项
注意点1:条件判断使用if标签
数值型使用:<if test="phone != null and phone != 0">phone,</if>
字符串使用:<if test="name != null and name != ''">ip,</if>
注意点2:${schema} 中$充当占位符,可以用来输入租户名
注意点3:<foreach>标签在使用中有两种形式
形式1:<foreach item="item" collection="arr" separator="," open="(" close=")" index="">
形式2:<foreach collection="conditionMap.keys" item="item" index="index" separator="and">
注意点4:有的 index="",有的index="index",这个我没测试过,是不是只要不用这个index属性,设置哪种都不影响?
注意点5:形参是list、array、map 时,在具体使用<foreach>标签时解析方式都不太一样,需要留意。
三、准备工作
封装工具类SqlSessionUtils
package com.mybatis.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* Date:2021/11/27
* Author:ybc
* Description:
*/
public class SqlSessionUtils {
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
e.printStackTrace();
}
return sqlSession;
}
}
封装实体类User
package com.mybatis.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* @Author 211145187
* @Date 2023/4/17 22:33
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
//id
private Integer id;
//用户名称
private String username;
//用户密码
private String password;
//用户手机号码
private String mobile;
public User(String username, String password, String mobile, Integer gender) {
this.username = username;
this.password = password;
this.mobile = mobile;
this.gender = gender;
}
public User(String username, Integer gender) {
this.username = username;
this.gender = gender;
}
}
四、CRUD模板
0.如果是pgsql需要创建系列;如果是mysql则不需要
DROP SEQUENCE IF EXISTS sid_001.business_server_id_seq CASCADE;
CREATE SEQUENCE sid_001.business_server_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE sid_001.business_server_id_seq OWNER TO postgres;
1.查询
<font color='red'>语法:SELECT * FROM table_name;</font>
注意:
1、查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射
关系
resultType
:自动映射,用于属性名和表中字段名一致的情况
resultMap
:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况
2、当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常
TooManyResultsException;但是若查询的数据只有一条,可以使用实体类或集合作为返回值
4.1.1 传入id查询一个实体类对象
/**
* 根据用户id查询用户信息
* @param id
* @return
*/
User getUserById(@Param("id") Integer id);
<select id="getUserById" resultType="User">
select * from litemall_user where id = #{id}
</select>
4.1.2 查询一个list集合
/**
* 查询所有用户信息
* @return
*/
List<User> getUserList();
<select id="getUserList" resultType="User">
select * from litemall_user
</select>
4.1.3 查询用户的总记录数
/**
* 查询用户的总记录数
* @return
* 在MyBatis中,对于Java中常用的类型都设置了类型别名
* 例如:java.lang.Integer-->int|integer
* 例如:int-->_int|_integer
* 例如:Map-->map,List-->list
*/
int getCount();
<select id="getCount" resultType="_integer">
select count(id) from t_user
</select>
4.1.4 (了解即可)查询一条数据为map集合
import org.apache.ibatis.annotations.Param;
/**
* 根据用户id查询用户信息为map集合
* @param id
* @return
*/
Map<String, Object> getUserToMap(@Param("id") int id);
<select id="getUserToMap" resultType="map">
select * from t_user where id = #{id}
</select>
<!--结果:{password=123456, sex=男, id=1, age=23, username=admin}-->
4.1.5 (了解即可)查询多条数据为map集合
若查询出的数据有多条:
- 可以通过实体类类型的list集合接收
- 可以通过map类型的list集合接收
- 可以在mapper接口的方法上添加@MapKey注解,此时就可以将每条数据转换的map集合作为值,以某个字段的值作为键,放在同一个map集合中
方式一:
/**
* 查询所有用户信息为map集合
* @return
* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此
时可以将这些map放在一个list集合中获取
*/
List<Map<String, Object>> getAllUserToMap();
<select id="getAllUserToMap" resultType="map">
select * from t_user
</select>
方式二:
import org.apache.ibatis.annotations.MapKey;
/**
* 查询所有用户信息为map集合
* @return
* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,并
且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的
map集合
*/
@MapKey("id")
Map<String, Object> getAllUserToMap();
<select id="getAllUserToMap" resultType="map">
select * from t_user
</select>
结果:
<!--
{
1={password=123456, sex=男, id=1, age=23, username=admin},
2={password=123456, sex=男, id=2, age=23, username=张三},
3={password=123456, sex=男, id=3, age=23, username=张三}
}
-->
4.1.6 传入id数组参数查询集合为list
/**
* 根据id数组查询集合为list
* @Author 211145187
* @Date 2023/4/24 22:55
* @param arr id数组
* @param schema 域名或者数据库名
* @Return list
**/
List<User> getListByIdArr(@Param("arr") int[] arr, @Param("schema") String schema);
<select id="getListByIdArr" resultType="User">
SELECT * FROM ${schema}.litemall_user
WHERE
id in
<foreach item="item" collection="arr" separator="," open="(" close=")" index="">
#{item}
</foreach>
</select>
4.1.7 传入map参数查询实体类对象(了解即可)
User checkLoginByMap(Map<String, Object> map);
方式1:
<select id="checkLoginByMap" resultType="User">
select * from litemall.litemall_user where username = #{username} and password = #{password}
</select>
--------------------------------------------------------------------------
方式2:
<select id="checkLoginByMap" resultType="User">
select * from litemall_user
<where>
<foreach collection="map.keys" item="item" index="index" separator="and">
${item}=#{map.${item}}
</foreach>
</where>
</select>
@Test
public void testCheckLoginByMap(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("username", "张三");
map.put("password", "123456");
User user = mapper.checkLoginByMap(map);
System.out.println(user);
}
4.1.8 传入list参数查询集合为list
List<User> getListByIdList(@Param("list") List<Integer> list);
<select id="getListByIdList" resultType="User">
SELECT * FROM litemall_user
WHERE id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="">
#{item}
</foreach>
</select>
@Test
public void getListByIdList(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
System.out.println(mapper.getListByIdList(list));
}
4.1.9 传入map参数封装在对象中,查询集合信息
↓ 针对mysql数据库
传参类长这样,sortColumn对应的map存储键值对是里面的数据
"sortColumn": {
"alarmLevel": "asc",
"createTime": "desc",
}
AlarmVo实体类
//排序列
private Map<String, String> sortColumn = new HashMap<>();
Dao层
/**
* 分页查询当前告警
* @param alarm
* @param page
* @param
*/
List<Alarm> selectCurrentAlarm(AlarmVo alarm, Page<Alarm> page);
xml
<select id="selectCurrentAlarm" parameterType="com.hero.lte.ems.fm.model.AlarmVo" resultMap="BaseResultMap">
SELECT * FROM fmalarm_current WHERE filterFlag is null
<if test="sortColumn != null and sortColumn.size() > 0">
order by
<foreach item="item" index="key" collection="sortColumn.entrySet()" separator=",">
<if test="item.value != null and item.value != ''">
${item.key} ${item.value}
</if>
</foreach>
</if>
<if test="sortColumn == null or sortColumn.size() == 0">
order by createtime desc
</if>
</select>
2.新增
<font color='red'>语法: 第一种形式无需指定要插入数据的列名,只需提供被插入的值即可:
INSERT INTO table_name VALUES (value1,value2,value3,...);</font><font color='red'>第二种形式需要指定列名及被插入的值:
INSERT INTO table_name (column1,column2,column3,...) VALUES (value1,value2,value3,...);</font>
4.2.1 单条新增返回主键:(传参为对象)
如果需要返回主键ID,请设置useGeneratedKeys="true" keyProperty="id"
int insertUser(@Param("user") User user);
方式1:
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
insert into litemall.litemall_user(username, password, mobile) values(#{user.username}, #{user.password}, #{user.mobile})
</insert>
-----------------------------------------------------------------
方式2:
<insert id="insertUserReturnPrimary" parameterType="User" useGeneratedKeys="true" keyProperty="id">
insert into litemall_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="user.gender != null and user.gender != 0">gender,</if>
<if test="user.username != null and user.username != ''">username,</if>
<if test="user.password != null and user.password != ''">password,</if>
<if test="user.mobile != null and user.mobile != ''">mobile,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="user.gender != null and user.gender != 0">#{user.gender},</if>
<if test="user.username != null and user.username != ''">#{user.username},</if>
<if test="user.password != null and user.password != ''">#{user.password},</if>
<if test="user.mobile != null and user.mobile != ''">#{user.mobile},</if>
</trim>
</insert>
@Test
public void insertUser(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
User user = new User(null, "同学1", "123456", "15197289663");
System.out.println(mapper.insertUser(user));
}
4.2.2 (了解即可)批量新增:(传参为Map)
int batchInsertByMap(@Param("map") Map<String, String> map);
<insert id="batchInsertByMap">
insert into litemall_user
<foreach collection="map.keys" item="key" index="index" open="(" separator="," close=")">
${key}
</foreach>
values
<foreach collection="map.keys" item="key" index="index" open="(" separator="," close=")">
#{map.${key}}
</foreach>
</insert>
//批量新增:(传参为Map)
@Test
public void batchInsertByMap(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
Map<String, String> map = new HashMap<>();
map.put("username", "同学6");
map.put("gender", "1");
mapper.batchInsertByMap(map);
}
4.2.3 批量新增:(传参为List)
int batchInsertByList(@Param("list") List<User> list);
<insert id="batchInsertByList">
insert into litemall_user(username, gender) values
<foreach collection='list' item='item' index='index ' separator=', '>
(#{item.username}, #{item.gender})
</foreach>
</insert>
//批量新增:(传参为List)
@Test
public void batchInsertByList(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
List<User> list = new ArrayList<>();
list.add(new User("同学7", 0));
list.add(new User("同学8", 0));
System.out.println(mapper.batchInsertByList(list));
}
4.2.4单条新增且返回自增主键
int saveServer(@Param("systemId") String systemId, @Param("flowMain") FlowMain flowMain);
<insert id="saveServer" parameterType="com.hytera.nm.aiap.dms.bean.FlowMain">
<selectKey resultType="java.lang.Long" keyProperty="flowMain.id" order="BEFORE" >
SELECT nextval('${systemId}.flow_main_id_sequence') AS id
</selectKey>
insert into ${systemId}.flow_main
(id,flow_type,applicant_user_id,applicant_user_name,applicant_police_num,applicant_vpn_node_string,
applicant_vpn_node_name,applicant_phone,status,application_notes,comment,approval_status,process_status,ts)
values(#{flowMain.id},#{flowMain.flowType},#{flowMain.applicantUserId},#{flowMain.applicantUserName}, #{flowMain.applicantPoliceNum},#{flowMain.applicantVpnNodeString},
#{flowMain.applicantVpnNodeName},#{flowMain.applicantPhone},#{flowMain.status},#{flowMain.applicationNotes}, #{flowMain.comment},#{flowMain.approvalStatus},#{flowMain.processStatus},#{flowMain.ts})
</insert> <update id="modifyApprovalStatus" parameterType="com.hytera.nm.aiap.dms.bean.requestData.ModifyApprovalStatus">
update ${systemId}.flow_main
set
status = ${currentStatus},
approver_user_id = ${approverUserId},
approver_user_name = ${approverUserName},
approval_opinion = ${approvalOpinion},
approval_status = ${approvalStatus}
where
id = ${id}
</update>
<font color='red'>注意:在MyBatis中,\<selectKey> 元素用于在执行插入语句之前或之后从数据库中获取主键值,并将其设置到参数对象中。order 属性用于指定获取主键值的时机,可以设置为 BEFORE 或 AFTER。
当设置为 BEFORE 时,MyBatis 在执行插入语句之前会先执行 \<selectKey> 中的查询来获取主键值,然后将主键值设置到参数对象中的指定属性中。
当设置为 AFTER 时,MyBatis 在执行插入语句之后会执行 \<selectKey> 中的查询来获取主键值,然后将主键值设置到参数对象中的指定属性中。
在你的情况下,order="BEFORE" 表示在执行插入语句之前会先获取主键值,并将其设置到 flowMain 对象的 id 属性中。
即:也就是说如果想给id复制拼接sql,那么必须写values(#{flowMain.id},而不能写values(#{id}这样写会报错,也就是所如果外面传id可以写(#{id},如果是\<selectKey> 获取的必须写#{flowMain.id}</font>
3.修改
<font color='red'>语法:UPDATE table_name SET column1=value1,column2=value2 WHERE some_column=some_value;</font>
4.3.1 单条更新:(传参为对象)
int updateUser(@Param("user") User user);
<update id="updateUser">
update litemall_user
<set>
<if test="user.username !=null and user.username !=''">
username = #{user.username},
</if>
<if test="user.gender != null and user.gender != 0">
gender = #{user.gender},
</if>
</set>
where id = #{user.id}
</update>
@Test
public void modifyUser(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
User user = new User(3, "1111", 1);
System.out.println(mapper.updateUser(user));
}
4.3.2 批量更新:(传参为集合)
总结:通过xml可以看出,传参为list还是Map其实xml写法差不多
@Test
public void batchUpdateByList(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
List<User> list = new ArrayList<>();
list.add(new User(18, "同学12", 1));
list.add(new User(19, "同学13", 1));
System.out.println(mapper.batchUpdateByList(list));
}
int batchUpdateByList(@Param("list") List<User> list);
<update id="batchUpdateByList">
<foreach collection='list' item='item' index='index' separator='; '>
update litemall_user
<set>
<if test="item.username != null and item.username !=''">
username = #{item.username},
</if>
<if test="item.gender != null and item.gender != 0">
gender = #{item.gender},
</if>
</set>
where id = #{item.id}
</foreach>
</update>
4.3.3 (了解即可)批量更新:(传参为Map且map种包含list集合)
注意前提:数据库必须设置allowMultiQueries=true,否则批量更新会报错
举例:jdbc.url=jdbc:mysql://IP:3306/litemall?allowMultiQueries=true
int batchUpdateByMap(Map<String, Object> map);
方式1:
<update id="batchUpdateByMap">
<foreach collection='paramMap' item='item' index='index' separator='; '>
update litemall_user set
username = #{item.username},
gender = #{item.gender}
where id = #{item.id}
</foreach>
</update>
------------------------------------------------------------
方式2:
<update id="batchUpdateByMap">
<foreach collection='paramMap' item='item' index='index' separator='; '>
update litemall_user
<set>
<if test="item.username != null and item.username !=''">
username = #{item.username},
</if>
<if test="item.gender != null and item.gender != 0">
gender = #{item.gender}
</if>
</set>
where id = #{item.id}
</foreach>
</update>
@Test
public void batchUpdateByMap(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
List<User> list = new ArrayList<>();
list.add(new User(18, "同学9", 1));
list.add(new User(19, "同学10", 1));
Map<String, Object> map = new HashMap<>();
map.put("paramMap", list);
System.out.println(mapper.batchUpdateByMap(map));
}
4.删除
<font color='red'>语法: DELETE FROM table_name WHERE some_column=some_value;</font>
4.4.1 根据id删除一条:(传参为对象)
@Test
public void deleteById(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
User user = new User();
user.setId(3);
System.out.println(mapper.deleteById(user));
}
int deleteById(@Param("user") User user);
<delete id="deleteById">
delete from litemall_user where id=#{user.id}
</delete>
4.4.2 批量删除:(传参为List)
@Test
public void batchDeleteByList(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
System.out.println(mapper.batchDeleteByList(list));
}
int batchDeleteByList(@Param("list") List<Integer> list);
<delete id="batchDeleteByList">
DELETE FROM litemall_user
WHERE id IN
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</delete>
本人其他相关文章链接
1.一、MyBatis简介:MyBatis历史、MyBatis特性、和其它持久化层技术对比、Mybatis下载依赖包流程
2.二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作)
3.三、MyBatis核心配置文件详解
4.四、MyBatis获取参数值的两种方式(重点)
5.五、MyBatis的增删改查模板(参数形式包括:String、对象、集合、数组、Map)
6.六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性
7.七、MyBatis自定义映射resultMap
8.八、(了解即可)MyBatis懒加载(或者叫延迟加载)
9.九、MyBatis动态SQL
10.十、MyBatis的缓存
11.十一、MyBatis的逆向工程
12.十二、MyBatis分页插件
重要信息
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。