ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Mybatis-plus的便捷增删改查【部分】【代码】

2022-05-28 01:31:56  阅读:188  来源: 互联网

标签:Insert -- 改查 dept plus emp Mybatis values DEPTNO


Mybatis-plus官方文档

Mybatis-plus官方文档

本文联合 lombok 插件使用,用到链式写法,需要 lombok 依赖

示例数据库文件

-- 建表语句
create table emp
(
EMPNO int, -- 员工号
ENAME varchar(10), -- 员工姓名
JOB varchar(9), -- 工作岗位
MGR int, -- 经理的员工号,外键
HIREDATE date, -- 入职时间
SAL double, -- 底薪
COMM double, -- 提成
DEPTNO int, -- 部门编号
primary key(EMPNO)
);

CREATE TABLE dept 
(
DEPTNO int, -- 部门编号
DNAME varchar(13), -- 部门名称
LOC VARCHAR(13), -- 部门地点
primary key(DEPTNO)
);
-- 建表语句
commit;
-- 插入数据
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7369,'SMITH','CLERK',7902,'2003-12-17',800,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7499,'ALLEN','SALESMAN',7698,'2007-9-3',1600,300,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7521,'WARD','SALESMAN',7698,'2005-3-8',1250,500,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7566,'JONES','MANAGER',7839,'2007-7-7',2975,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7654,'MARTIN','SALESMAN',7698,'2005-5-6',1250,1400,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7698,'BLAKE','MANAGER',7839,'2005-5-6',2850,null,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7782,'CLARK','MANAGER',7839,'2010-3-1',2450,null,10);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7788,'SCOTT','ANALYST',7566,'2005-5-6',3000,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7839,'KING','PRESIDENT',null,'2001-5-6',5000,null,10);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7844,'TURNER','SALESMAN',7698,'2008-8-8',1500,0,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7876,'ADAMS','CLERK',7788,'2005-5-6',1100,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7900,'JAMES','CLERK',7698,'2005-5-6',950,null,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7902,'FORD','ANALYST',7566,'2005-5-6',3000,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7934,'MILLER','CLERK',7782,'2005-5-6',1300,null,10);
Insert into DEPT (DEPTNO,DNAME,LOC) values (10,'ACCOUNTING','NEW YORK');
Insert into DEPT (DEPTNO,DNAME,LOC) values (20,'RESEARCH','DALLAS');
Insert into DEPT (DEPTNO,DNAME,LOC) values (30,'SALES','CHICAGO');
Insert into DEPT (DEPTNO,DNAME,LOC) values (40,'OPERATIONS','BOSTON');
commit;

基本增删改查【测试类先试一下awa】

package com.muhuai.mybatis_plus;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.muhuai.mybatis_plus.mapper.DeptMapper;
import com.muhuai.mybatis_plus.model.domain.Dept;
import com.muhuai.mybatis_plus.service.DeptService;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.Map;

// 这个测试会能够十分明显地看出lombok的精妙之处【反正很牛逼这个玩意】
// 应该说链式写法被lombok支持?
@SpringBootTest
@MapperScan(basePackages = "com.muhuai.mybatis_plus.mapper")
public class MybatisplusApplicationTests
{
    @Autowired
    // 这个报错不影响运行 想要这个不报错的话,在接口上注释Repository
    private DeptMapper deptMapper;
    @Autowired
    private DeptService deptService;

    @Test
    // 插入测试
    public void insert_dept()
    {
        // 添加一个dept
        // 这个写法应该是lpmbok支持的【咱就是说真的精妙】
        // 注意一个小细节:Java中的字符串用""括起来,如果用''括起来,编译器认为这是一个字符
        Dept dept = new Dept().setDeptno(3).setDname("Muhuai").setLoc("Beijing");
        deptMapper.insert(dept);

        // Service的方法
        // save(Entity)
        // deptMapper.insert(dept); == deptService.save(dept);
        deptService.save(dept);

        // saveBatch(Entity) 批量添加
        // saveOrUpdate(Entity) 如果Entity的主键已经在数据库存在,则update,否则insert
        // saveOrUpdateBatch 同理
    }

    @Test
    // 删除数据测试
    public void delete_dept()
    {
        // deleteById() 根据id删除实体
        // deleteBatchIds(Collection) 删除一堆id对应的实体

        // deleteByMap(Map) 删除Map键值对对应的实体
        // 如 : 删除dept表中deptno = 3 && dname = Muhuai 的实体
        Map<String,Object> map = new HashMap<>();
        map.put("deptno",3);
        map.put("dname","Muhuai");
        deptMapper.deleteByMap(map);

        // delete(Wrapper<> wrapper) 条件构造器
        // 注意!!!这个Wrapper是baomidou里面的
        // Wrapper是接口,它有几个实现类,详情见wiki.suncaper.net

        // QueryWrapper - 这个缺点是硬编码,里面的条件是写死的
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deptno",11).eq("dname","Muhuai");
        deptMapper.delete(queryWrapper);

        // LambdaQueryWrapper
        LambdaQueryWrapper<Dept> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 这个Dept::getXXX 的方法就是在Dept类的 @Data注解实现的
        lambdaQueryWrapper.eq(Dept::getDeptno,1).eq(Dept::getDname,"Muhuai");
        deptMapper.delete(lambdaQueryWrapper);
    }

    @Test
    // 修改测试
    public void update_ddept()
    {
        // updateById()

        // update(Entity,wrapper) 执行语句的结果是 符合wrapper条件的实体被替换成Entity的值?
        // 不过这个主键应该是不能改的【就是说即便在这里写了setdeptno,deptno也不会被改变awa】
        Dept updated_dept = new Dept().setDeptno(23).setDname("MH").setLoc("Beijing");
        LambdaQueryWrapper<Dept> query_wrapper = new LambdaQueryWrapper<>();
        query_wrapper.eq(Dept::getDeptno,2).eq(Dept::getDname,"Muhuai");
        deptMapper.update(updated_dept,query_wrapper);
    }

    @Test
    // 查询测试
    public void select_dept()
    {
        // Mapper层提供的接口
        // selectById() 根据一个id查询
        // selectBatchIds() 根据一堆id查询
        // selectList(wrapper) 根据条件构造器查询,结果是一个List
        // selectCount() 查询个数
        // selectMaps()
        // selectOne 一定要保证只能查询到一个结果,不然就要报错

        // Service层提供的接口
    }
}

自定义SQL

// 自定义SQL 一定是写在 mapper ,这边调用 mapper 层的方法
// mapper 层的方法对应 mapper.xml,【alt + enter 真的好用啊!!!】
// 如果 mapper 的方法名为 get 之类的,alt + enter 会直接生成 sql 到 mapper.xml

// 自定义sql获取参数的类型 mapper.xml如何写
// 单个基本数据类型 -- 直接 #{} 获取参数就行 如:where id = #{id}

// 多个基本数据类型 -- 参数必须取别名,然后 ${} 获取别名
// 用 @Param 注解在参数前面取一个名字
// 这样不容易出错awa

// 单个对象 -- 对象形式的参数也最好取别名,对象传参传送的是一堆键值对
// ${对象.属性名}
// 多个对象同理

// 反正取别名nice

练习题

一对一的关联查询

理解为:通过查询 A,然后通过 A,查询到 B。如:查询员工的姓名及其直接上级的姓名【这里将一张表当成两张表看待】

一般表现为类似于这样的 SQL
select emp.ename,emp_t.ename from emp as emp,emp as emp_t where emp.mgr = emp_t.empno;
select ename,dname from emp,dept where job = 'CLERK' and dept.deptno = emp.deptno;

  1. 先去 A 的实体类里面添加字段,字段类型为 B

注意!!!

添加的这个字段不是数据表的字段,但是Mybatis默认实体类的字段对应数据表结构,为解决这个问题,需要在这个字段上面加注解

@TableField(exist = false)

  1. 去mapper.xml里面创建返回类型【直接上代码】

注意!!!

标签中的 column 对应查询返回的字段名【或者说对应数据库字段名】
为了避免 association 标签中返回这个字段名和其他的重复,需要更改查询语句【用 as 给别名】

select emp.ename,emp_t.ename as mgr_ENAME

<!--  查询员工的直接上级  -->
<!-- type对应实体类的位置 -->
<resultMap id="MgrResultMap" type="com.muhuai.mybatis_plus.model.domain.Emp">
    <result column="ENAME" property="ename" />
    <association property="mgrid" javaType="com.muhuai.mybatis_plus.model.domain.Emp">
        <result column="mgr_ENAME" property="ename"/>
    </association>
</resultMap>

<!-- resultMap是刚刚创建的那个 -->
<select id="getemp3" resultMap="MgrResultMap">
        select emp.ename,emp_t.ename as mgr_ENAME from muhuaifeature.emp as emp,muhuaifeature.emp as emp_t
            where emp.mgr = emp_t.empno;
</select>
  1. 测试使用
// -- 3.列出所有员工的姓名及其直接上级的姓名。
    @Test
    public void s_emp_3()
    {
        // 这个是一对一的查询,去Emp里面加一个字段
        List<Emp> emp_3 = new ArrayList<>();
        emp_3 = empMapper.getemp3();
        for(Emp emp:emp_3)
            System.out.println(emp.getEname() + ":" + emp.getmgr_name());
    }

一对多的关联查询

和一对一类似,不过这个是 通过查询 A,通过 A 查询到一堆 B
如:查询部门名称和这些部门的员工信息 | 查询和 'Muhuai' 年龄一样的人的选课

一般表现为这样的 SQL
select dept.deptno,dname,emp.* from dept left outer join emp on emp.deptno = dept.deptno;

  1. 同理,在 A 中添加字段【列表类型】

注意!!!

添加的这个字段不是数据表的字段,但是Mybatis默认实体类的字段对应数据表结构,为解决这个问题,需要在这个字段上面加注解

@TableField(exist = false)

  1. 同理,在 mapper.xml 创建返回类型【还是直接上代码】

注意!!!

标签中的 column 对应查询返回的字段名【或者说对应数据库字段名】
为了避免 association 标签中返回这个字段名和其他的重复,需要更改查询语句【用 as 给别名】

select emp.ename,emp_t.ename as mgr_ENAME

注意!!!

<!-- 部门的成员信息 -->
<resultMap id="DeptEmpMap" type="com.muhuai.mybatis_plus.model.domain.Dept">
    <id column="D_DEPTNO" property="deptno" />
    <result column="DNAME" property="dname" />
    <result column="LOC" property="loc" />
    <collection property="dept_emp" ofType="com.muhuai.mybatis_plus.model.domain.Emp">
        <id column="EMPNO" property="empno" />
        <result column="ENAME" property="ename" />
        <result column="JOB" property="job" />
        <result column="MGR" property="mgr" />
        <result column="HIREDATE" property="hiredate" />
        <result column="SAL" property="sal" />
        <result column="COMM" property="comm" />
        <result column="DEPTNO" property="deptno" />
    </collection>
</resultMap>

<select id="getdept5" resultMap="DeptEmpMap">
        select dept.deptno as D_DEPTNO,dname,emp.* from
            muhuaifeature.dept left outer join muhuaifeature.emp on emp.deptno = dept.deptno;
</select>
  1. 测试使用
// -- 5.列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门
    @Test
    public void s_dept_5()
    {
        List<Dept> dept_5 = new ArrayList<>();
        dept_5 = deptMapper.getdept5();
        for(Dept dept:dept_5)
        {
            System.out.println("部门名称: " + dept.getDname());
            List<Emp> temp_emp = dept.getDept_emp();
            for(Emp emp:temp_emp)
            {
                System.out.println(dept.getDept_emp().toString());
            }
        }
    }

示例代码

Mapper.java 文件里的接口函数自动生成,这里就不放了

另外一些重复的函数我也就不放了,放一点典型的就好

实体类中的注解

    // 声明这个字段不是数据表中的
    // 员工的直接上级
    @TableField(exist = false)
    private Emp mgrid;
    // 员工所属的部门
    @TableField(exist = false)
    private Dept emp_dept;
    // 员工总工资
    @TableField(exist = false)
    private Double total_sal;
    // 每种工作的最低工资
    @TableField(exist = false)
    private Double lest_sal;
    // 年薪
    @TableField(exist = false)
    private Double year_sal;

    // 返回直接上级Emp的名字
    // 其实这一个方法可以不写的,返回的类型是Emp,里面的getename方法就可以直接实现
    public String getmgr_name()
    {
        return mgrid.ename;
    }

另外,经过测试,新加的字段因为 @Data 注解的原因,也是自动生成 get | set 方法

EmpMapper.xml

查询的返回值可以表示成 引用对象A | 引用对象B | 基础类型C

<!-- 查询员工部门及总工资 -->
<resultMap id="TotalsalResultMap" type="com.muhuai.mybatis_plus.model.domain.Emp">
    <result column="ENAME" property="ename" />
    <association property="emp_dept" javaType="com.muhuai.mybatis_plus.model.domain.Dept">
        <result column="DNAME" property="dname"/>
    </association>
    <association property="total_sal" javaType="java.lang.Double">
        <result column="total_sal" property="total_sal"/>
    </association>
</resultMap>

<select id="getemp14" resultMap="TotalsalResultMap">
        select ename,dname,(ifnull(sal,0) + ifnull(comm,0)) as total_sal from
            emp,dept where emp.deptno = dept.deptno;
</select>

引申问题

$ 和 # 的区别

  • 是占位符,防止SQL注入,调用PreparedStatement
  • 以拼接的方式写进SQL,有SQL注入风险,调用Statement

举例来说 查询 name 中带有 "mu" 的数据

SQL语句:select * from user where name like '%mu%';

那么这个语句在 mapper.xml 中应该怎么写?

select * from user where name like '%#{name}%'
select * from user where name like '%'#{name}'%'
select * from user where name like '%${name}%'

因为 name 作为 String 类型的数据,自带 '' ,那么第二句的 SQL
select * from user where name like '%'mu'%';

$ 直接进行字符串拼接 -- 对应正确的 SQL 语句

SQL中字段名和主键名不匹配怎么办

标签:Insert,--,改查,dept,plus,emp,Mybatis,values,DEPTNO
来源: https://www.cnblogs.com/Muhuai/p/16319691.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有