JavaWeb开发 —— MyBatis基本操作

目录

一、环境准备

二、删除操作实现

1. 根据主键删除

2. 删除(预编译SQL)

2.1  SQL注入

 2.2  参数占位符

三、新增操作实现

1. 新增代码实现

 2. 新增(主键返回)

四、更新操作实现

五、查询操作实现

1. 根据ID查询

1.1  数据封装 

 2.  查询(条件查询)

 2.1  参数名说明


通过实例案例进行学习MyBatis基本操作的增删查改。

需求说明:根据资料提供页面原型及需求,完成员工管理的需求开发

功能列表:

① 查询:根据主键ID查询、条件查询。

② 新增    ③ 更新

④ 删除:根据主键ID删除、根据主键ID批量删除。

一、环境准备

  • 准备数据库表emp。
-- 部门管理
create table dept(
    id int unsigned primary key auto_increment comment '主键ID',
    name varchar(10) not null unique comment '部门名称',
    create_time datetime not null comment '创建时间',
    update_time datetime not null comment '修改时间'
) comment '部门表';

insert into dept (id, name, create_time, update_time) values(1,'学工部',now(),now()),(2,'教研部',now(),now()),(3,'咨询部',now(),now()), (4,'就业部',now(),now()),(5,'人事部',now(),now());



-- 员工管理
create table emp (
  id int unsigned primary key auto_increment comment 'ID',
  username varchar(20) not null unique comment '用户名',
  password varchar(32) default '123456' comment '密码',
  name varchar(10) not null comment '姓名',
  gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',
  image varchar(300) comment '图像',
  job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师',
  entrydate date comment '入职时间',
  dept_id int unsigned comment '部门ID',
  create_time datetime not null comment '创建时间',
  update_time datetime not null comment '修改时间'
) comment '员工表';

INSERT INTO emp
	(id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time) VALUES
	(1,'jinyong','123456','金庸',1,'1.jpg',4,'2000-01-01',2,now(),now()),
	(2,'zhangwuji','123456','张无忌',1,'2.jpg',2,'2015-01-01',2,now(),now()),
	(3,'yangxiao','123456','杨逍',1,'3.jpg',2,'2008-05-01',2,now(),now()),
	(4,'weiyixiao','123456','韦一笑',1,'4.jpg',2,'2007-01-01',2,now(),now()),
	(5,'changyuchun','123456','常遇春',1,'5.jpg',2,'2012-12-05',2,now(),now()),
	(6,'xiaozhao','123456','小昭',2,'6.jpg',3,'2013-09-05',1,now(),now()),
	(7,'jixiaofu','123456','纪晓芙',2,'7.jpg',1,'2005-08-01',1,now(),now()),
	(8,'zhouzhiruo','123456','周芷若',2,'8.jpg',1,'2014-11-09',1,now(),now()),
	(9,'dingminjun','123456','丁敏君',2,'9.jpg',1,'2011-03-11',1,now(),now()),
	(10,'zhaomin','123456','赵敏',2,'10.jpg',1,'2013-09-05',1,now(),now()),
	(11,'luzhangke','123456','鹿杖客',1,'11.jpg',5,'2007-02-01',3,now(),now()),
	(12,'hebiweng','123456','鹤笔翁',1,'12.jpg',5,'2008-08-18',3,now(),now()),
	(13,'fangdongbai','123456','方东白',1,'13.jpg',5,'2012-11-01',3,now(),now()),
	(14,'zhangsanfeng','123456','张三丰',1,'14.jpg',2,'2002-08-01',2,now(),now()),
	(15,'yulianzhou','123456','俞莲舟',1,'15.jpg',2,'2011-05-01',2,now(),now()),
	(16,'songyuanqiao','123456','宋远桥',1,'16.jpg',2,'2010-01-01',2,now(),now()),
	(17,'chenyouliang','123456','陈友谅',1,'17.jpg',NULL,'2015-03-21',NULL,now(),now());
  • 创建一个新的springboot工程,选择引入对应的起步依赖(mybatis、mysql驱动、lombok)。
  • application.properties中引入数据库连接信息。
  • 创建对应的实体类Emp(实体类属性采用驼峰命名)。
  • 准备Mapper接口EmpMapper。

二、删除操作实现

1. 根据主键删除

//接口方法
@Delete("delete from emp where id = #{id}")
    public void delete(Integer id);

//实现类 
@Test
public void testDelete(){
     empMapper.delete(17);
}

注意事项:如果mapper接口方法形参只有一个普通类型的参数,#{ ... }里面的属性名可以随便写,如:#[id}、#value}。

2. 删除(预编译SQL)

在上述根据id主键删除元素,当我们执行单元测试时,我们可以看到数据库表结构发生变化,但是我们并不能直观了解到MyBatis框架底层到底执行了什么Sql语句以及执行结构。而我们可以借助MyBatis框架日志看到这些,日志默认关闭。

  • 可以在application.properties中,打开mybatis日志,并指定输出到控制台。
    #指定mybatis输出日志的位置,输出控制台
    mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    

在MyBatis的mapper接口中声明的SQL语句使用 #{ } 占位符,最终会被问号 ? 替代, 生成预编译SQL语句。问号为预编译SQL语句中的参数占位符,最终执行会将SQL语句以及下方参数一起发送给数据库,数据库执行SQL语句时又会将参数替换问号完成操作。

② 预编译对比与直接拼接参数的优势:

  • 性能更高
  • 更安全(防止SQL注入

2.1  SQL注入

SQL注入 是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。
① 未防止SQL注入:直接拼接参数

正常情况下,数据库执行查询操作 -> count(*) = 1表示用户名和密码存在且正确,登录成功。

但是通过SQL注入攻击服务器:登录成功!(此时where 后条件一直成立)

select count(*) from emp where username = 'zhangwuji' and password = '123456';
select count(*) from emp where username = 'zhangwuji' and password = '111';
select count(*) from emp where username = 'wuieuwiueiwuiew' and password = '' or '1' = '1';

② 防止SQL注入: 通过 #{ } 占位符

 2.2  参数占位符

#{ ... }

  • 执行SQL时,会将 #{...} 替换为?,生成预编译SQL,会自动设置参数值。
  • 使用时机:参数传递,都使用#{...}

${ ... }

  • 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题。
  • 使用时机:如果对表名、列表进行动态设置时使用。

三、新增操作实现

1. 新增代码实现

//接口方法
@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 void insert(Emp emp);

//实现类 
@Test
    public void testInsert(){
        //构建员工对象
        Emp emp = new Emp();
        emp.setUsername("Tom");
        emp.setName("汤姆");
        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());
        emp.setDeptId(1);

        //执行新增员工信息操作
        empMapper.insert(emp);
    }

MyBatis日志:

 2. 新增(主键返回)

① 描述:在数据添加成功后,需要获取插入数据库数据的主键。如:添加套餐数据时,还需要维护套餐菜品关系表数据。

 ② 实现:@Options():会自动将生成的主键值,赋值给emp对象的id属性。

@Options(keyProperty = "id",useGeneratedKeys = true)
@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 void insert(Emp emp);
}

四、更新操作实现

//接口方法
@Update("update emp set username = #{username},name=#{name},gender=#{gender},image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime}" +
        "where id = #{id};")
    public void update(Emp emp);

//实现类 
@Test
    public void testUpdate(){
        //构建员工对象
        Emp emp = new Emp();
        emp.setId(18);
        emp.setUsername("Jery");
        emp.setName("杰瑞");
        emp.setImage("2.jpg");
        emp.setGender((short)1);
        emp.setJob((short)2);
        emp.setEntrydate(LocalDate.of(2000, 1, 1));
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(1);

        //执行更新员工信息操作
        empMapper.update(emp);
    }

MyBatis日志:

五、查询操作实现

1. 根据ID查询

//接口方法
@Select("select * from emp where id = #{id};")
    public Emp getById(Integer id);

//实现类 
@Test
    public void testSeclet(){
        Emp emp = empMapper.getById(10);
        System.out.println(emp);
    }

MyBatis日志:

在控制台中,我们可以看到username、password、name、gender等信息都查询出来,但是dept_id、createTime、updateTime均为null空值,并没有被封装进来,但是数据库表结构是有值的。这就涉及到MyBatis的数据封装

1.1  数据封装 

  • 实体类属性名 和 数据库表查询返回的字段名一致,mybatis会自动封装。
  • 如果 实体类属性名 和 数据库表查询返回的字段名不一致,不能自动封装。

解决方案:

给字段起别名,通过别名与实体类属性一致。

@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 getById(Integer id);

通过@Results@Result注解手动映射封装。

@Results({
        @Result(column = "dept_id",property = "deptId"),
        @Result(column = "create_time",property = "createTime"),
        @Result(column = "update_time",property = "updateTime")
})
@Select("select * from emp where id = #{id};")
    public Emp getById(Integer id);

开启 MyBatis的驼峰命名自动映射开关 。(推荐)

//application.properties
mybatis.configuration.map-underscore-to-camel-case=true

 2.  查询(条件查询)

//接口方法
@Select("select * from emp where name like '%${name}%' and gender = #{gender} and " +
        "entrydate between #{begin} and #{end} order by update_time desc;")
    public List<Emp>  getList(String name, short gender, LocalDate begin,LocalDate end);

//实现类 
@Test
    public void testList(){
        List<Emp> list = empMapper.getList("张", (short)1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
        System.out.println(list);
    }

MyBatis日志:

此时我们注意到,当SQL语句中存在模糊匹配,在关键字前后加 % 百分号,此时这是一个字符串。在字符串中无法使用用 #{ } ,而我们使用的 ${ } 字符串拼接,其生成的不是一个预编译SQL,就有可能出现性能低、不安全、存在SQL注入问题。

我们通过MySQL提供的 Concat 函数解决这一问题:

@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +
        "entrydate between #{begin} and #{end} order by update_time desc;")
    public List<Emp>  getList(String name, short gender, LocalDate begin,LocalDate end);

 2.1  参数名说明

① 在springboot的 2.x 版本#{ }中参数名与形参名直接对应。

 ② 在springboot的 1.x 版本 / 单独使用mybatis需要在每一个形参加上@Param注解为其制定一个名字与#{ }中参数名再对应。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hgngy.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值