五、MyBatis的增删改查模板(参数形式包括:String、对象、集合、数组、Map)

说明:方便后续根据场景直接拷贝代码

@[toc]

一、foreach 标签的属性含义

foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。 foreach元素的属性主要有 item,index,collection,open,separator,close。 item集合中每一个元素进行迭代时的别名, index表示在迭代过程中,每次迭代到的位置, open该语句以什么开始, separator在每次进行迭代之间以什么符号作为分隔 符, close以什么结束, 在使用foreach的时候最关键的也是最容易出错的就是collection属性, 该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的, 主要有一下3种情况:

     如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
c 复制代码
  如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
javascript 复制代码
  如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了

二、使用注意事项

xml 复制代码
注意点1:条件判断使用if标签
数值型使用:<if test="phone != null  and phone != 0">phone,</if>
字符串使用:<if test="name != null  and name != ''">ip,</if>
xml 复制代码
注意点2:${schema} 中$充当占位符,可以用来输入租户名
xml 复制代码
注意点3:<foreach>标签在使用中有两种形式
形式1:<foreach item="item" collection="arr" separator="," open="(" close=")" index="">
形式2:<foreach collection="conditionMap.keys" item="item" index="index" separator="and">
xml 复制代码
注意点4:有的 index="",有的index="index",这个我没测试过,是不是只要不用这个index属性,设置哪种都不影响?
xml 复制代码
注意点5:形参是list、array、map 时,在具体使用<foreach>标签时解析方式都不太一样,需要留意。

三、准备工作

封装工具类SqlSessionUtils

java 复制代码
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

kotlin 复制代码
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则不需要

java 复制代码
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.查询

语法:SELECT * FROM table_name;
注意:

1、查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射

关系

resultType:自动映射,用于属性名和表中字段名一致的情况

resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况

2、当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常

TooManyResultsException;但是若查询的数据只有一条,可以使用实体类或集合作为返回值

4.1.1 传入id查询一个实体类对象

less 复制代码
/**
* 根据用户id查询用户信息
* @param id
* @return
*/
User getUserById(@Param("id") Integer id);
csharp 复制代码
<select id="getUserById" resultType="User">
        select * from litemall_user where id = #{id}
</select>

4.1.2 查询一个list集合

csharp 复制代码
/**
* 查询所有用户信息
* @return
*/
List<User> getUserList();
csharp 复制代码
<select id="getUserList" resultType="User">
	select * from litemall_user
</select>

4.1.3 查询用户的总记录数

markdown 复制代码
/**
* 查询用户的总记录数
* @return
* 在MyBatis中,对于Java中常用的类型都设置了类型别名
* 例如:java.lang.Integer-->int|integer
* 例如:int-->_int|_integer
* 例如:Map-->map,List-->list
*/
int getCount();
sql 复制代码
<select id="getCount" resultType="_integer">
	select count(id) from t_user
</select>

4.1.4 (了解即可)查询一条数据为map集合

less 复制代码
import org.apache.ibatis.annotations.Param;

/**
* 根据用户id查询用户信息为map集合
* @param id
* @return
*/
Map<String, Object> getUserToMap(@Param("id") int id);
xml 复制代码
<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集合中

方式一:

perl 复制代码
/**
* 查询所有用户信息为map集合
* @return
* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此
时可以将这些map放在一个list集合中获取
*/
List<Map<String, Object>> getAllUserToMap();
csharp 复制代码
<select id="getAllUserToMap" resultType="map">
	select * from t_user
</select>

方式二:

python 复制代码
import org.apache.ibatis.annotations.MapKey;

/**
* 查询所有用户信息为map集合
* @return
* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,并
且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的
map集合
*/
@MapKey("id")
Map<String, Object> getAllUserToMap();
xml 复制代码
<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

less 复制代码
/**
    * 根据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);
perl 复制代码
<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参数查询实体类对象(了解即可)

arduino 复制代码
User checkLoginByMap(Map<String, Object> map);
csharp 复制代码
方式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>
ini 复制代码
@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

less 复制代码
List<User> getListByIdList(@Param("list") List<Integer> list);
perl 复制代码
<select id="getListByIdList" resultType="User">
        SELECT * FROM litemall_user
        WHERE id in
        <foreach item="item" collection="list" separator="," open="(" close=")" index="">
            #{item}
        </foreach>
</select>
ini 复制代码
@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存储键值对是里面的数据

java 复制代码
"sortColumn": {
        "alarmLevel": "asc",
        "createTime": "desc",
}

AlarmVo实体类

java 复制代码
//排序列
private Map<String, String> sortColumn = new HashMap<>();

Dao层

java 复制代码
/**
 * 分页查询当前告警
 *  @param alarm
 * @param page
 * @param
 */
List<Alarm> selectCurrentAlarm(AlarmVo alarm, Page<Alarm> page);

xml

java 复制代码
<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.新增

语法: 第一种形式无需指定要插入数据的列名,只需提供被插入的值即可: INSERT INTO table_name VALUES (value1,value2,value3,...);
第二种形式需要指定列名及被插入的值: INSERT INTO table_name (column1,column2,column3,...) VALUES (value1,value2,value3,...);

4.2.1 单条新增返回主键:(传参为对象)

如果需要返回主键ID,请设置useGeneratedKeys="true" keyProperty="id"

less 复制代码
int insertUser(@Param("user") User user);
ini 复制代码
方式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>        
ini 复制代码
@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)

less 复制代码
int batchInsertByMap(@Param("map") Map<String, String> map);
lua 复制代码
<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>
arduino 复制代码
//批量新增:(传参为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)

less 复制代码
int batchInsertByList(@Param("list") List<User> list);
csharp 复制代码
<insert id="batchInsertByList">
        insert into litemall_user(username, gender) values
        <foreach collection='list' item='item' index='index ' separator=', '>
            (#{item.username}, #{item.gender})
        </foreach>
</insert>
csharp 复制代码
//批量新增:(传参为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单条新增且返回自增主键

java 复制代码
int saveServer(@Param("systemId") String systemId, @Param("flowMain") FlowMain flowMain);
java 复制代码
<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>

注意:在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}

3.修改

语法:UPDATE table_name SET column1=value1,column2=value2 WHERE some_column=some_value;

4.3.1 单条更新:(传参为对象)

less 复制代码
int updateUser(@Param("user") User user);
bash 复制代码
<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>
ini 复制代码
@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写法差不多

csharp 复制代码
@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));
}
less 复制代码
int batchUpdateByList(@Param("list") List<User> list);
bash 复制代码
<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

arduino 复制代码
int batchUpdateByMap(Map<String, Object> map);
bash 复制代码
方式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>
ini 复制代码
@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.删除

语法: DELETE FROM table_name WHERE some_column=some_value;

4.4.1 根据id删除一条:(传参为对象)

ini 复制代码
@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));
}
less 复制代码
int deleteById(@Param("user") User user);
bash 复制代码
<delete id="deleteById">
        delete from litemall_user where id=#{user.id}
</delete>

4.4.2 批量删除:(传参为List)

ini 复制代码
@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));
}
less 复制代码
int batchDeleteByList(@Param("list") List<Integer> list);
perl 复制代码
<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分页插件

重要信息

相关推荐
Wis4e4 分钟前
数据挖掘导论——第二章:数据
人工智能·数据挖掘
蜡笔小新星7 分钟前
OpenCV中文路径图片读写终极指南(Python实现)
开发语言·人工智能·python·opencv·计算机视觉
六月的翅膀9 分钟前
C++/OpenCV:Mat初始化赋值误区
人工智能·opencv·计算机视觉
西猫雷婶32 分钟前
python学智能算法(七)|KNN邻近算法
算法
好评笔记33 分钟前
AIGC视频生成模型:慕尼黑大学、NVIDIA等的Video LDMs模型
人工智能·深度学习·机器学习·计算机视觉·aigc·transformer·面试八股
Francek Chen36 分钟前
【现代深度学习技术】卷积神经网络06:卷积神经网络(LeNet)
人工智能·pytorch·深度学习·神经网络·cnn
用户90803219692538 分钟前
OpenCV三大经典项目实战 掌握计算机视觉核心技能-|果fx
算法
大势智慧41 分钟前
使用模方修模,模型的UV能修改,只出一张图吗?
人工智能·uv·三维建模·实景三维
go546315846544 分钟前
复现无人机的项目,项目名称为Evidential Detection and Tracking Collaboration
人工智能
Vitalia1 小时前
⭐算法OJ⭐经典题目分类索引(持续更新)
算法