【java web篇】MyBatis实现增删改查

个人简介

  • 作者简介:大家好,我是阿牛,全栈领域优质创作者。
  • 个人主页:馆主阿牛
  • 支持我:点赞+收藏⭐️+留言
  • 系列专栏:java 小白到高手的蜕变
  • 格言:要成为光,因为有怕黑的人!
    请添加图片描述

目录

    • 个人简介
  • 前言
    • 查询
      • 查看详情
      • 条件查询
      • 动态条件查询
        • 多条件动态查询
        • 单条件动态查询
    • 添加和修改
      • 添加
      • 修改
    • 删除
    • 使用注解方实增删改查
  • 结语

前言

上一节主要写了MyBatis入门案例以及Mapper代理,这节主要结合前面的知识实现MyBatis的增删改查,涉及动态sql的使用!

查询

查询所有在入门案例里已经举例过了,这里不再写案例!

查看详情

首先补充mybatis-config.xml核心配置文件:
【java web篇】MyBatis实现增删改查_第1张图片
可以添加类型别名,然后对应的sql映射文件里resultType就可以直接简写返回值类型了,而且不区分大小写!
【java web篇】MyBatis实现增删改查_第2张图片
下面进入案例:

【java web篇】MyBatis实现增删改查_第3张图片
【java web篇】MyBatis实现增删改查_第4张图片

public static void main(String[] args) throws IOException {
        //1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //3. 执行sql (只有这块需要手写,其他步骤直接复制)
        MemberMapper memberMapper = sqlSession.getMapper(MemberMapper.class);

        int id = 2;
        Member member = memberMapper.selectById(id);
        System.out.println(member);

        //4. 释放资源
        sqlSession.close();
    }

【java web篇】MyBatis实现增删改查_第5张图片
这里要对参数占位符作出说明:

mybatis提供了两种参数占位符:

  • #{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是PreparedStatement
  • ${} :拼接SQL。底层使用的是 Statement ,会存在SQL注入问题。

接下来来看另为的问题:

【java web篇】MyBatis实现增删改查_第6张图片
这里sql语句>是没有问题的,但小于号<是xml标签的开始符号,会报错!
【java web篇】MyBatis实现增删改查_第7张图片
有两种解决方式:

方式一:使用<的转义字符:

<select id="selectById" resultType="member">
     select * from member where id < #{id}
select>

方式二:使用CDATA区:

<select id="selectById" resultType="member">
   select * from member where id 
     
    #{id}
select>

CDATA区里的字符会当做纯文本处理!

条件查询

sql映射文件:MemberMapper.xml
【java web篇】MyBatis实现增删改查_第8张图片
而该功能有2个参数,我们就需要考虑定义接口时,参数应该如何定义。Mybatis针对多参数有多种实现:

1.使用 @Param(“参数名称”) 标记每一个参数,在映射配置文件中就需要使用 #{参数名称} 进行占位!

【java web篇】MyBatis实现增删改查_第9张图片

int age = 28;
 String name = "张";
 // 模糊匹配,参数处理
 name = '%' + name + '%';

 List<Member> members = memberMapper.selectByCondition(age,name);
 System.out.println(members);

【java web篇】MyBatis实现增删改查_第10张图片

2.将多个参数封装成一个 实体对象 ,将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和实体类属性名保持一致。

【java web篇】MyBatis实现增删改查_第11张图片

int age = 28;
String name = "张";
// 模糊匹配,参数处理
name = '%' + name + '%';
// 封装对象
Member member = new Member();
member.setAge(age);
member.setName(name);

List<Member> members = memberMapper.selectByCondition(member);
System.out.println(members);

3.将多个参数封装到map集合中,将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容}时,里面的内容必须和map集合中键的名称一致。

int age = 28;
String name = "张";
// 模糊匹配,参数处理
name = '%' + name + '%';
// 封装map对象
HashMap map = new HashMap();
map.put("age",age);
map.put("name",name);
List<Member> members = memberMapper.selectByCondition(map);
System.out.println(members);

动态条件查询

多条件动态查询

上述功能实现存在很大的问题,假如我们在做开发遇到用户在输入条件时,这个需求肯定不会所有的条件都填写,一种是对于不同填写情况判断,用不同的sql,但这样比较麻烦,写的sql也多,所以MyBatis提供了动态sql,可以帮助我们一条语句就搞定这种搜索查询情况!


 <select id="selectByCondition" resultType="member">
     select *
     from member
     where age = #{age}
     and name like #{name};
 select>

上面的意思就是说,这样的sql查询必须是两个或者多个参数都有才能查出来,而我们的需求是两个甚至多个条件任选都满足查询,这就是动态sql,只需一条sql就搞定,那下面就来看看怎么搞!


<select id="selectByCondition" resultType="member">
    select *
    from member
    where
    <if test="age != null">
        age = #{age}
    if>
    <if test="name != null and name != ''">
        and name like #{name}
    if>
select>

用动态sql的if标签即可满足!if标签可以判断参数是否有值,使用test属性判断!
【java web篇】MyBatis实现增删改查_第12张图片
可以看到此时只有一个条件,依然满足!
但是如果是第一个条件没有,此时就会出问题:


报错也很明显,多了一个and,对于这种情况有两种解决方式!

方式一:不常用

```xml

<select id="selectByCondition" resultType="member">
    select *
    from member
    where 1=1
    <if test="age != null">
        and age = #{age}
    if>
    <if test="name != null and name != ''">
        and name like #{name}
    if>
select>

加一个1=1恒等式不就行了,但我们sql可不这么写,所以用第二个方法!

方法二:使用where 标签

  • 作用:
    • 替换where关键字
    • 会动态的去掉第一个条件前的 and
    • 如果所有的参数没有值则不加where关键字
<select id="selectByCondition" resultType="member">
     select *
     from member
     <where>
         <if test="age != null">
             age = #{age}
         if>
         <if test="name != null and name != ''">
             and name like #{name}
         if>
     where>
select>

【java web篇】MyBatis实现增删改查_第13张图片

单条件动态查询

还有一个情况就是我们的条件只有一个,但我们不知道是哪一个条件!

这就需要使用到 choose(when,otherwise)标签 实现, 而 choose 标签类似于Java 中的switch语句。


<select id="selectByCondition" resultType="member">
    select *
    from member
    where 
    <choose> 
        <when test="age != null">  
            age = #{age}
        when>
        <when test="name != null and name != ''">
            and name like #{name}
        when>
    choose>
select>

但这样有个问题是当单个条件都没有时会多出一个where,此时跟上面一样,有两种解决方案!

方案一:借助otherwise多写一个恒等式


 <select id="selectByCondition" resultType="member">
     select *
     from member
     where
     <choose> 
         <when test="age != null">  
             age = #{age}
         when>
         <when test="name != null and name != ''">
             and name like #{name}
         when>
         <otherwise>  
             1 = 1
         otherwise>  
     choose>
 select>

方案二 :用where标签


<select id="selectByCondition" resultType="member">
    select *
    from member
    <where>
        <choose> 
            <when test="age != null">  
                age = #{age}
            when>
            <when test="name != null and name != ''">
                and name like #{name}
            when>
        choose>
    where>
select>

【java web篇】MyBatis实现增删改查_第14张图片

添加和修改

添加

sql映射文件:

<insert id="add">
   insert into member (name,gender,age)
    values (#{name},#{gender},#{age});
insert>

mapper接口

void add(Member member);

主要代码:

package com.aniu;

import com.aniu.mapper.MemberMapper;
import com.aniu.pojo.Member;
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;

/**
 * @Author:Aniu
 * @Date:2023/4/13 22:07
 * @description 增加
 */
public class MyBatisDemo4 {
    public static void main(String[] args) throws IOException {
        //1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // SqlSession sqlSession = sqlSessionFactory.openSession(true);  // 开启自动提交
        //3. 执行sql (只有这块需要手写,其他步骤直接复制)
        MemberMapper memberMapper = sqlSession.getMapper(MemberMapper.class);
        String name = "阿牛";
        String gender = "男";
        int age = 21;
        Member member = new Member();
        member.setGender(gender);
        member.setName(name);
        member.setAge(age);

        memberMapper.add(member);
        //手动提交事务
        sqlSession.commit();
        //4. 释放资源
        sqlSession.close();
    }
}

【java web篇】MyBatis实现增删改查_第15张图片

在数据添加成功后,有时候需要获取插入数据库数据的主键(主键是自增长)。

此时直接从pojo类中获取不到,sql映射文件里的insert语句要添加两个属性:

<insert id="add" useGeneratedKeys="true" keyProperty="id">
   insert into member (name,gender,age)
    values (#{name},#{gender},#{age});
insert>

修改

有修改部分字段,有全部修改,这里依旧使用动态sql来实现全部需求

sql映射文件:

<update id="update">
  update member
   <set>
       <if test="name != null and name != ''">
           name = #{name},
       </if>
       <if test="gender != null and gender != ''">
           gender = #{gender},
       </if>
       <if test="age != null">
           age = #{age}
       </if>
   </set>
   where id = #{id};
</update>

依然有逗号问题,所以用set标签处理

mapper接口:

int update(Member member);

主要实现:

public class MyBatisDemo4 {
    public static void main(String[] args) throws IOException {
        //1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // SqlSession sqlSession = sqlSessionFactory.openSession(true);  // 开启自动提交
        //3. 执行sql (只有这块需要手写,其他步骤直接复制)
        MemberMapper memberMapper = sqlSession.getMapper(MemberMapper.class);
        String name = "aniu";
        int id = 5;
        Member member = new Member();
        member.setName(name);
        member.setId(id);
        int count = memberMapper.update(member);
        System.out.println(count);
        //手动提交事务
        sqlSession.commit();
        //4. 释放资源
        sqlSession.close();
    }
}

【java web篇】MyBatis实现增删改查_第16张图片

删除

根据id删除:

void deleteById(int id);
<delete id="deleteById">
	delete from member where id = #{id};
delete>

批量删除:

/**
* 批量删除
*/
void deleteByIds(int[] ids);

编写SQL语句:
在 MemberMapper.xml 映射配置文件中编写删除多条数据的 statement 。

编写SQL时需要遍历数组来拼接SQL语句。Mybatis 提供了 foreach 标签供我们使用:

  • foreach 标签:用来迭代任何可迭代的对象(如数组,集合)。
    • collection 属性:mybatis会将数组参数,封装为一个Map集合。
      默认:array = 数组
      使用@Param注解改变map集合的默认key的名称。
    • item 属性:本次迭代获取到的元素。
    • separator 属性:集合项迭代之间的分隔符。 foreach 标签不会错误地添加多余的分隔符。也就是最 后一次迭代不会加分隔符。
    • open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次
    • close 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次
<delete id="deleteByIds">
    delete from member where id
    in
    <foreach collection="array" item="id" separator="," open="(" close=")">
        #{id}
    foreach>
    ;
delete>

使用@Param注解改变map集合的默认key的名称后:

void deleteByIds(@Param("ids") int[] ids);

【java web篇】MyBatis实现增删改查_第17张图片

主要测试代码:

package com.aniu;

import com.aniu.mapper.MemberMapper;
import com.aniu.pojo.Member;
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;

/**
 * @Author:Aniu
 * @Date:2023/4/14 19:36
 * @description 批量删除
 */
public class MyBatisDemo5 {
    public static void main(String[] args) throws IOException {
        //1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // SqlSession sqlSession = sqlSessionFactory.openSession(true);  // 开启自动提交
        //3. 执行sql (只有这块需要手写,其他步骤直接复制)
        MemberMapper memberMapper = sqlSession.getMapper(MemberMapper.class);
        int[] ids = {1,2,3};
        memberMapper.deleteByIds(ids);
        //手动提交事务
        sqlSession.commit();
        //4. 释放资源
        sqlSession.close();
    }
}

【java web篇】MyBatis实现增删改查_第18张图片

使用注解方实增删改查

使用注解开发会比配置文件开发更加方便。如下就是使用注解进行开发:

@Select(value = "select * from member where id = #{id}")
public Member select(int id);

注意:

  • 注解是用来替换映射配置文件方式配置的,所以使用了注解,就不需要再映射配置文件中书写对应的 statement。

Mybatis 针对 CURD 操作都提供了对应的注解,已经做到见名知意。如下:

  • 查询 :@Select
  • 添加 :@Insert
  • 修改 :@Update
  • 删除 :@Delete

注意:在官方文档中 入门 中有这样的一段话:

在这里插入图片描述
所以,注解完成简单功能,配置文件完成复杂功能。这里对注解的使用不再举例!

结语

如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。

系列专栏
flask框架入门到实战
软磨 css
硬泡 javascript

你可能感兴趣的:(java,小白到高手的蜕变,mybatis,java,前端)