Mybatis进阶应用-增删改查

113 阅读2分钟

本文章为黑马javaweb课程学习笔记 项目结构如下

image.png

  • 首先进行数据准备,准备emp表以及对应的实体类
  • emp表

image.png

  • Emp实体类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Short gender;
    private String image;
    private Short job;
    private LocalDate entrydate;
    private Integer deptId;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

接下来是mapper包下的EmpMapper接口

package mybatistest.mapper;

import mybatistest.pojo.Account;
import mybatistest.pojo.Emp;
import org.apache.ibatis.annotations.*;
import java.time.LocalDate;
import java.util.List;

@Mapper
//可以直接生成实体类并将其放入Bean之中
public interface EmpMapper {
    @Select(value = "select * from test.account;")
    public List<Account> selectAccount();
    @Select("select * from emp;")
    public List<Emp> selectEmp();
    //由mybatis提供#{id},动态获取id的值
    //当只传递进一个变量时{}里面可以随便写名称,但是当存在多个变量时,则变量名必须对应
    //#{}是采取预编译方法拼接sql语句,而${}是直接拼接字符串
    @Delete("delete from emp where id = #{id};")
    public int deleteEmp(Integer id);
//    @Insert("insert into emp (id, username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values " +
//            "(#{id},#{username},#{name},#{},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})"),id自增,类之中未定义id,使用报错
    @Options(keyProperty = "id",useGeneratedKeys = true)
    //使用该注解意味着会拿到生成后的主键,keyProperty为将生成的主键封装到对象的id之中,useGeneratedKeys为获取生成的主键
    @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
        " values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
    public int insertEmp(Emp emp);
    @Update("update emp set username=#{username},name=#{name},gender=#{gender},image=#{image},job=#{job},update_time=#{updateTime},entrydate=#{entrydate} where id = #{id};")
    public void update(Emp emp);
    //@Select无法自动进行映射,无法经将dept_id映射为deptId
//    @Select(value = "select * from emp where id = #{id};")
//    public Emp selectById(Integer id);
    //解决方案1,给查询结果起别名
//    @Select("select id, username, password, name, gender, image, job, entrydate, dept_id deptId, create_time createTime, update_time updateTime from emp where id=#{id};")
//    public Emp selectById(Integer id);
    //解决方案2,采取@Results,@Result分别进行映射
//    @Results({
//            @Result(column = "dept_id" ,property = "deptId"),
//            @Result(column = "create_time",property = "createTime"),
//            @Result(column = "update_time",property = "updateTime")
//    })
    //解决方案3,开启驼峰命名的自动映射
    //在配置文件当中#开启mybatis的驼峰命名自动映射开关 a_column ------> aCloumn
    //#mybatis.configuration.map-underscore-to-camel-case=true
    @Select(value = "select * from emp where id = #{id};")
    public Emp selectById(Integer id);
    //条件查询
//    @Select("select * from emp where name like '%张%' and entrydate between '2000-01-01' and '2020-01-01' order by update_time desc ;")
//    public List<Emp> selectIf(String name, LocalDate begin, LocalDate end);
    //该方法会报错,原因是字符串内部不可以使用#
//    @Select("select * from emp where name like '%#{name}%' and entrydate between '2000-01-01' and '2020-01-01' order by update_time desc ;")
//    public List<Emp> selectIf(String name, LocalDate begin, LocalDate end);
    //可以使用$方法进行直接的字符串拼接解决上述原因,但是该方法无法进行预编译,无法防止sql注入
//    @Select("select * from emp where name like '%${name}%' and entrydate between '2000-01-01' and '2020-01-01' order by update_time desc ;")
//    public List<Emp> selectIf(String name, LocalDate begin, LocalDate end);
    //采取concat能完美解决上述问题
//    @Select("select * from emp where name like concat('%','张','%') and entrydate between #{begin} and #{end} order by update_time desc ;")
//以下三个方法采取xml文件映射
    public List<Emp> selectIf(String name, short gender, LocalDate begin, LocalDate end);
    public void updateXml(Emp emp);
    public void deletByIds(List<Integer> ids);
}

image.png

image.png 简单功能建议使用注解开发,复杂的功能建议使用xml文件开发,尤其是涉及到多个条件筛选时,可以使用where,set,if标签进行搭配来进行动态SQL

image.png

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间必须与mapper接口名一致且要放在同名包之下-->
<mapper namespace="mybatistest.mapper.EmpMapper">
<!--    为了提高代码的可重用性,可以将共同的sql语句使用sql标签进行抽取-->
<!--    在使用时使用include标签进行使用-->
    <sql id="commonSelect">
        select * from emp
    </sql>
    <update id="updateXml">
        update emp
        <!--        set标签和where一样都具有去除多余字段功能,where去除多余and和or,set去除多余,-->
        <set>
            <if test="username != null">
                username=#{username},
            </if>
            <if test="name != null">
                name=#{name},
            </if>
            <if test="gender != null">
                gender=#{gender},
            </if>

            <if test="image != null">
                image=#{image},
            </if>
            <if test="job != null">
                job=#{job},
            </if>
            <if test="updateTime != null">
                update_time=#{updateTime},
            </if>
            <if test="entrydate != null">
                entrydate=#{entrydate}
            </if>
        </set>
        where id = #{id};
    </update>
    <delete id="deletByIds">
        delete from emp where id in
<!--        foreach标签主要用于批量操作之中-->
<!--        collection为遍历的集合-->
<!--        item为元素-->
<!--        separator为分隔符-->
<!--        open为拼接开始符号-->
<!--        close为拼接结束符号-->
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>
    <!--    id值必须要与方法名一致-->
    <!--    返回类型为单条记录返回类型,比如List<Emp>单条记录返回类型为Emp-->
    <!--    写完了不要忘记把原本接口注释删掉-->
    <select id="selectIf" resultType="mybatistest.pojo.Emp">
        <!--        动态sql案例-->
        <include refid="commonSelect"></include>
        <!--        如果不使用where标签而单纯的使用if标签,最终的sql语句可能会出现没有name标签但是存在and gender的情况,最终报错-->
        <!--        where标签会自动的去除and或者or的重复-->
        <where>
            <if test="name != null">
                name like concat('%',#{name},'%')
            </if>
            <if test="gender != null">
                or gender = #{gender}
            </if>
            <if test="begin != null and end != null">
                and entrydate between #{begin} and #{end}
            </if>
        </where>
        order by update_time desc ;
    </select>
</mapper>

image.png 所有测试程序如下

package mybatistest;

import mybatistest.mapper.EmpMapper;
import mybatistest.pojo.Account;
import mybatistest.pojo.Emp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

@SpringBootTest
class MybatisTestApplicationTests {

    @Autowired
    private EmpMapper empMapper;
    @Test
    public void testDelete(){
        if(empMapper.deleteEmp(15)==1){
            System.out.println("yes");
        }else{
            System.out.println("no");
        }
    }
    @Test
    public void testSelect(){
       List<Account> empList = empMapper.selectAccount();
       System.out.println(empList);
    }
    @Test
    public void testAccoun(){
        List<Emp> empList = empMapper.selectEmp();
        System.out.println(empList);
    }
    @Test
    public void testInsert(){
        Emp emp = new Emp();
        emp.setUsername("Tom5");
        emp.setName("汤姆3");
        emp.setImage("1.jpg");
        emp.setGender((short)1);
        emp.setJob((short)1);
        emp.setEntrydate(LocalDate.of(2000,1,1));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());

        if(empMapper.insertEmp(emp)==1){
            //未使用@Options,无法获取主键,故emp.getId()为null
            System.out.println("insert ok"+emp.getId());
        }
    }
    @Test
    public void updateEmp(){
        Emp emp = new Emp();
        emp.setId(18);
        emp.setUsername("Tom3");
        emp.setName("汤姆3");
        emp.setImage("1.jpg");
        emp.setGender((short)1);
        emp.setJob((short)1);
        emp.setEntrydate(LocalDate.of(2000,1,1));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.update(emp);
    }
    @Test
    public void testUapateXml(){
        Emp emp = new Emp();
        emp.setId(22);
        emp.setUsername("Tom3asad");
        empMapper.updateXml(emp);
    }
    @Test
    public void testSelectByid(){
        Emp emp = new Emp();
        emp = empMapper.selectById(2);
        System.out.println(emp);
    }
    @Test
    public void testSelectIf(){
        String name = "张";
        short gender = 1;
        LocalDate begin = LocalDate.of(2000,1,1);
        LocalDate end = LocalDate.of(2020,1,1);
        List<Emp> empList = empMapper.selectIf(name,gender,begin,end);
        System.out.println(empList);
    }
    @Test
    public void testDeletByIds(){
        List<Integer> ids = Arrays.asList(18,19,20);
        empMapper.deletByIds(ids);
    }
}

还有最后的配置文件,其中包括了如何开启日志以及开启驼峰命名的自动映射

#配置数据库连接信息
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/example
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=

#配置mybatis的日志, 指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#开启mybatis的驼峰命名自动映射开关 a_column ------> aCloumn
mybatis.configuration.map-underscore-to-camel-case=true