【JavaEE 进阶(六)】Mybatis操作数据库

news2024/11/15 17:40:18

❣博主主页: 33的博客❣
▶️文章专栏分类:JavaEE◀️
🚚我的代码仓库: 33的代码仓库🚚
🫵🫵🫵关注我带你了解更多进阶知识

在这里插入图片描述

目录

  • 1.前言
  • 2.JDBC操作
  • 3.Mybatis
    • 3.1Mybatis入门
    • 3.1.1准备工作
      • 3.1.2配置数据库连接
      • 3.1.2写持久层代码
    • 3.2MyBatis基础操作
      • 3.2.1打印日志
      • 3.2.2参数传递
      • 3.2.3增
      • 3.2.3删
      • 3.2.4改
      • 3.2.5查
    • 3.3MyBatis XML配置
      • 3.3.1配置XML文件
      • 3.3.2Mapper接口
      • 3.3.3增
      • 3.3.4删
      • 3.3.5改
      • 3.3.6查
      • #{}和${}区别
  • 4.数据库连接池
  • 5.总结

1.前言

在应用分层学习时,我们了解到web应⽤程序⼀般分为三层,即:Controller、Service、Dao。之前的案例中,请求流程如下:浏览器发起请求,先请求Controller,Controller接收到请求之后,调用Service进⾏业务逻辑处理,Service再调⽤Dao,但是Dao层的数据是Mock的,真实的数据应该从数据库中读取。我们知道在java中可以通过JDBC来操作数据库,但这样操作是非常复杂的,那在Spring Boot中有更简便的方法吗?接下来我们就进行学习吧!

2.JDBC操作

我们先了解一下通过JDBC来操作数据库:

  • 创建数据库连接池DataSource
  • 通过数据库连接池获取数据库连接Connection
  • 编写带有?占位符的sql语句
  • 替换占位符,指定要替换的数据库字段类型,要替换的值。
  • 使用Statement执行SQL语句
  • 查询操作:返回结果ResultSet,更新操作:返回更新的数据量
  • 处理结果集
  • 释放资源
//创建数据库
create database if not exists library default character set utf8mb4;   
use library;-- 
//创建表
create table if not exists soft_bookrack (
  book_name varchar(32) NOT NULL,
  book_author varchar(32) NOT NULL,
  book_isbn varchar(32) NOT NULL primary key
 );

JDBC具体代码(以新增为例)

public class SimpleJdbcOperation {
  private final DataSource dataSource;
  public SimpleJdbcOperation(DataSource dataSource) {
        this.dataSource = dataSource;
    }
//添加⼀本书
  public void addBook() {
    Connection connection = null;
    PreparedStatement stmt = null;
    try {
//获取数据库连接  
connection=dataSource.getConnection();         
//创建语句
stmt=connection.prepareStatement("insert into soft_bookrack (book_name, book_author, book_isbn) values (?,?,?);");
 //参数绑定
stmt.setString(1, "Spring in Action");
stmt.setString(2, "Craig Walls");
stmt.setString(3, "9787115417305");
 //执⾏语句
 stmt.execute();
 } catch (SQLException e) {
//处理异常信息
 } finally {
//清理资源
 try {
  if (stmt != null) {
   stmt.close();
   }
    if (connection != null) {
   connection.close();
     }
     } catch (SQLException e) {
                //
     }
   }
 }

从上诉代码可见,对于JDBC来说,整个操作是非常麻烦的,,我们不但要拼接每⼀个参
数,而且还要按照模板代码的⽅式,⼀步步的操作数据库,并且在每次操作完,还要⼿动关闭连接等,而所有的这些操作步骤都需要在每个⽅法中重复书写.那有没有⼀种方法,可以更简单、更方便的操作数据库呢?当然是有的,那就是Mybatis,它可以帮助我们更方便的操作数据库。

3.Mybatis

Mybatis是持久层框架,用于简化JDBC的开发。持久层就是指持久化操作的层,通常指数据访问层,用来操作数据库的。
在这里插入图片描述
简单来说Mybatis是更简单完成程序和数据库交互的框架。

3.1Mybatis入门

3.1.1准备工作

创建Spring boot工程,并导入mybatis的依赖和mysql驱动包
在这里插入图片描述
项目创建完成之后,会自动在pom文件中导入相关依赖。
在这里插入图片描述
数据准备:

CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
USE mybatis_test;
CREATE TABLE `userinfo` (
 `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
 `username` VARCHAR ( 127 ) NOT NULL,
 `password` VARCHAR ( 127 ) NOT NULL,
 `age` TINYINT ( 4 ) NOT NULL,
 `gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-⼥ 0-默认',
 `phone` VARCHAR ( 15 ) DEFAULT NULL,
 `delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
 `create_time` DATETIME DEFAULT now(),
 `update_time` DATETIME DEFAULT now(),
 PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; 
//添加⽤⼾信息
 INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
 VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
 INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
 VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
 INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
 VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
 INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
 VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

对应实体类:
与表中字段名一致

import lombok.Data;
 import java.util.Date;
 @Data
 public class UserInfo {
 private Integer id;
 private String username;
 private String password;
 private Integer age;
 private Integer gender;
 private String phone;
 private Integer deleteFlag;
 private Date createTime;
 private Date updateTime;
 }

3.1.2配置数据库连接

spring:
 datasource:
 url: jdbc:mysql://127.0.0.1:3306/mybatis_test?
characterEncoding=utf8&useSSL=false
 username: root//用户名
 password: root//密码
 driver-class-name: com.mysql.cj.jdbc.Driver

3.1.2写持久层代码

@Mapper
public interface UserInfoMapper {
 //查询所有⽤⼾
 @Select("select username, `password`, age, gender, phone from userinfo")
 public List<UserInfo> queryAllUser();
}

进行单元测试,自动生成
在这里插入图片描述

@SpringBootTest
class UserInfoMapperTest {
 @Autowired
 private UserInfoMapper userInfoMapper;
 @Test
 void queryAllUser() {
 List<UserInfo> userInfoList = userInfoMapper.queryAllUser();
 System.out.println(userInfoList);
 }
}

在这里插入图片描述

3.2MyBatis基础操作

3.2.1打印日志

在Mybatis当中我们可以借助⽇志, 查看到sql语句的执⾏、执⾏传递的参数以及执⾏结果在配置⽂件中进⾏配置即可:

mybatis:
 configuration: # 配置打印 MyBatis⽇志
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

在这里插入图片描述

3.2.2参数传递

如果要查找id为4的用户信息可以写为:

@Select("select username, `password`, age, gender, phone from userinfo where id= 4 ")
UserInfo queryById();

但是这样就把id写死了,不能修改,那么我们可以使用参数来优化:

@Select("select username, `password`, age, gender, phone from userinfo where id= #{id} ")
UserInfo queryById(Integer id);

当我们调用queryById时,传递不同的id值就可以查询出不同的信息。

3.2.3增

@Insert("insert into userinfo (username, `password`, age, gender, phone) values (#{username},#{password},#{age},#{gender},#{phone})")
Integer insert(UserInfo userInfo);

测试:

@Test
void insert() {
 UserInfo userInfo = new UserInfo();
 userInfo.setUsername("zhaoliu");
 userInfo.setPassword("zhaoliu");
 userInfo.setGender(2);
 userInfo.setAge(21);
 userInfo.setPhone("18612340005");
 userInfoMapper.insert(userInfo);
}

3.2.3删

@Delete("delete from userinfo where id = #{id}")
void delete(Integer id);

测试

@Test
void delete() {
 userInfoMapper.delete(4);
}

3.2.4改

@Update("update userinfo set username=#{username} where id=#{id}")
void update(UserInfo userInfo);

测试

@Test
void  update() {
 UserInfo userInfo = new UserInfo();
 userInfo.setUsername("zhaoliu666");
 userInfo.setId(5);
 userInfoMapper.insert(userInfo);
}

3.2.5查

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
List<UserInfo> queryAllUser();

测试

@Test
void  queryAllUser() {;
 userInfoMapper.queryAllUser();
}

当我们查询的时候,我们发现有一些数值为空,但数据库中却有值是怎么回事呢?
在这里插入图片描述
MyBatis会根据方法的返回结果进行赋值,方法用对象UserInfo接收结果,就会根据对应UserInfo的属性进行赋值。
在这里插入图片描述
解决办法:
1.起别名

@Select("select id, username, `password`, age, gender, phone, delete_flag as deleteFlag, create_time as createTime, update_time as updateTime from userinfo")
public List<UserInfo> queryAllUser();

2.结果映射

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
@Results({
 @Result(column = "delete_flag",property = "deleteFlag"),
 @Result(column = "create_time",property = "createTime"),
 @Result(column = "update_time",property = "updateTime")
})
List<UserInfo> queryAllUser();

3.开启驼峰命名

mybatis:
 configuration:
   map-underscore-to-camel-case: true #配置驼峰⾃动转换

此时代码不用做任何处理,会把update_time转换为:updateTime并赋值

3.3MyBatis XML配置

MyBatis的开发方式有2种,注解和XML上面我们学习的都是通过注解实现的,接下来我们通过XML来实现。

3.3.1配置XML文件

配置XML文件路径,在resources/mapper下面,以Mapper.xml结尾的文件

mybatis:
 mapper-locations: classpath:mapper/**Mapper.xml

3.3.2Mapper接口

mapper文件种添加UserInfoXMlMapper类

@Mapper
public interface UserInfoXMlMapper {
 List<UserInfo> queryAllUser();
}

resources/mapper创建UserInfoXMLMapper.xml类,并添加XML固定格式

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserInfoMapper">
 <select id="queryAllUser" resultType="com.example.demo.model.UserInfo">
 select username,`password`, age, gender, phone from userinfo
 </select>
</mapper>

3.3.3增

Integer insertUser(UserInfo userInfo);
<insert id="insertUser">
insert into userinfo (username, `password`, age, gender, phone) values (#{username}, #{password}, #{age},#{gender},#{phone})
</insert>

3.3.4删

Integer deleteUser(Integer id);
<delete id="deleteUser">
 delete from userinfo where id = #{id}
</delete>

3.3.5改

Integer updateUser(UserInfo userInfo);
<update id="updateUser">
 update userinfo set username=#{username} where id=#{id}
</update>

3.3.6查

List<UserInfo> queryAllUser();
<select id="queryAllUser" resultType="com.example.demo.model.UserInfo">
 select id, username,`password`, age, gender, phone, delete_flag, 
create_time, update_time from userinfo
</select>

#{}和${}区别

@Select("select username, `password`, age, gender, phone from userinfo where username= ${name} ")
UserInfo queryByName(String name);

运行结果:
在这里插入图片描述
使用${}是直接进行字符串拼接,但是字符串作为参数时,需要添加’ ‘,使用 ${}不会拼接’ '。
解决

@Select("select username, `password`, age, gender, phone from userinfo where username= '${name}' ")
UserInfo queryByName(String name);

在这里插入图片描述
#{}与${}区别
1.性能更高
2.更安全(防止SQL注入)

@Select("select username, `password`, age, gender, phone from userinfo where username= '${name}' ")
List<UserInfo> queryByName(String name);

正常情况下:

@Test
void queryByName() {
 List<UserInfo> userInfos = userInfoMapper.queryByName("admin");
 System.out.println(userInfos);
 }
}

在这里插入图片描述
sql注入:

@Test
void queryByName() {
 List<UserInfo> userInfos = userInfoMapper.queryByName("' or 1='1");
 System.out.println(userInfos);
}

这时结果依然被正确查询出来了, 其中参数 or被当做了SQL语句的⼀部分。这时就会查询出所有的表中数据。
既然${}会有Sql注入的风险,那么它是否就没有用呢?实现排序,like查询的时候只能使用 ${}不能使用#{},例如:

@Select("select id, username, age, gender, phone, delete_flag, create_time, update_time " +"from userinfo order by id ${sort} ")
List<UserInfo> queryAllUserBySort(String sort);

这时候传入的sort不需要引号所以必须要使用${}

4.数据库连接池

数据库连接池负责分配、管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接,而不是再重新建⽴⼀个。
没有使用数据库连接池的情况: 每次执⾏SQL语句, 要先创建⼀个新的连接对象, 然后执⾏SQL语句, SQL语句执⾏完, 再关闭连接对象释放资源. 这种重复的创建连接, 销毁连接⽐较消耗资源
使用数据库连接池的情况: 程序启动时, 会在数据库连接池中创建⼀定数量的Connection对象, 当客⼾请求数据库连接池, 会从数据库连接池中获取Connection对象, 然后执⾏SQL, SQL语句执⾏完, 再把Connection归还给连接池

优点:

  1. 减少了⽹络开销
  2. 资源重⽤
  3. 提升了系统的性能

5.总结

利用MyBatis进行数据库的增删改查操作,使用驼峰转换时,要注意java中的属性和数据库中属性的对应关系,一般创建数据库时,表必备三字段: id, create_time, update_time,在表查询中, 避免使⽤ * 作为查询的字段列表, 标明需要哪些字段。

下期预告:MyBatis进阶

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1859751.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

13 物理层介质及设备

物理层介质及设备 一、线缆的连接 &#xff08;一&#xff09;线序 ​ 线序&#xff1a; RJ-45连接头12345678568A绿白绿橙白蓝蓝白橙棕白棕568B橙白橙绿白蓝蓝白绿棕白棕 ​ 1、2发送&#xff0c;3、6接收 &#xff08;二&#xff09;线缆的应用 1.线缆的连接 ​ 标准…

OpenHarmony 5.0 纯血鸿蒙系统

OpenHarmony-v5.0-Beta1 版本已于 2024-06-20 发布。 OpenHarmony 5.0 Beta1 版本标准系统能力持续完善&#xff0c;ArkUI 完善了组件通过 C API 调用的能力&#xff1b;应用框架细化了生命周期管理能力&#xff0c;完善了应用拉起、跳转的能力&#xff1b;分布式软总线连接能力…

MindManager2024思维导图软件重磅发布更新!

大家好啊&#xff01;&#x1f44b; 今天我超级激动要分享给大家一款改变我工作和学习方式的工具——MindManager2024思维导图软件&#xff01;这可不仅仅是个工具哦&#xff0c;它更像是我的私人思维助手&#xff0c;帮我整理思绪&#xff0c;规划时间&#xff0c;还能激发创新…

HTML+CSS 3D旋转登录表单

效果演示 实现了一个具有3D旋转效果的登录框&#xff0c;背景为太空图片&#xff0c;登录框位于太空中心&#xff0c;可以通过输入用户名和密码进行登录。登录框使用了CSS3的3D变换和动画效果&#xff0c;使其具有立体感和动态效果。同时&#xff0c;登录框的样式也经过精心设计…

TMC2209驱动模式详解

TMC2209驱动模式详解 1.TMC2209封装2.TMC2209引脚定义 1.TMC2209封装 2.TMC2209引脚定义

关于ONLYOFFICE8.1版本桌面编辑器测评——AI时代的领跑者

关于作者&#xff1a;个人主页 目录 一.产品介绍 1.关于ONLYOFFICE 2.关于产品的多元化功能 二.关于产品体验方式 1.关于套件的使用网页版登录 2.关于ONLYOFFICE本地版 三.关于产品界面设计 四.关于产品文字处理器&#xff08;Document Editor&#xff09; 1.电子表格&a…

破碎的像素地牢探险:游戏分享

软件介绍 《破碎的像素地牢》是开源一款地牢冒险探索类的游戏&#xff0c;融合了日系RPG经典风格&#xff0c;玩家将控制主角进行未知场景的探索。除了经典地牢玩法外&#xff0c;游戏还添加了更多创意内容&#xff0c;如黑屏状态前的挑战性等&#xff0c;使得游戏更加富有挑战…

【源码】Spring Data JPA原理解析之Auditing执行原理

Spring Data JPA系列 1、SpringBoot集成JPA及基本使用 2、Spring Data JPA Criteria查询、部分字段查询 3、Spring Data JPA数据批量插入、批量更新真的用对了吗 4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作 5、Spring Data JPA自定…

C#的无边框窗体项目模板 - 开源研究系列文章

继续整理和编写代码及博文。 这次将笔者自己整理的C#的无边框窗体项目的基本模板进行总结&#xff0c;得出了基于C#的.net framework的Winform的4个项目模板&#xff0c;这些模板具有基本的功能&#xff0c;即已经初步将代码写了&#xff0c;直接在其基础上添加业务代码即可&am…

Maya 白膜渲染简单教程

零基础渲染小白&#xff0c;没关系&#xff0c;一篇超简单教程带你学会渲染白膜。 先打开Maya&#xff0c;看看面板有没有渲染器&#xff0c;这里以Arnold为主。 要是没有这个&#xff0c;就去找插件管理器&#xff0c; Arnold的是mtoa&#xff0c;在搜索栏搜&#xff0c;然后把…

uni-app 微信小程序开发到发布流程

1. uni-app 微信小程序开发到发布流程 1.1. 新建一个uni-app 项目 1.2. 发行微信小程序 1.3. 微信开发者平台的微信小程序appid 复制进来&#xff08;点击发行&#xff09; 1.4. IDE may already started at port xxxx, trying to connect &#xff08;1&#xff09;关闭微信…

【Golang - 90天从新手到大师】Day14 - 方法和接口

一&#xff0e; go方法 go方法&#xff1a;在函数的func和函数名间增加一个特殊的接收器类型&#xff0c;接收器可以是结构体类型或非结构体类型。接收器可以在方法内部访问。创建一个接收器类型为Type的methodName方法。 func (t Type) methodName(parameter list) {}go引入…

解析JavaScript中逻辑运算符和||的返回值机制

本文主要内容&#xff1a;了解逻辑运算符 &&&#xff08;逻辑与&#xff09;和 ||&#xff08;逻辑或&#xff09;的返回值。 在JavaScript中&#xff0c;逻辑运算符 &&&#xff08;逻辑与&#xff09;和 ||&#xff08;逻辑或&#xff09;的返回值可能并不总…

大模型之-Seq2Seq介绍

大模型之-Seq2Seq介绍 1. Seq2Seq 模型概述 Seq2Seq&#xff08;Sequence to Sequence&#xff09;模型是一种用于处理序列数据的深度学习模型&#xff0c;常用于机器翻译、文本摘要和对话系统等任务。它的核心思想是将一个输入序列转换成一个输出序列。 Seq2Seq模型由两个主…

【仿真建模-anylogic】MarkupSegment代码解析

Author&#xff1a;赵志乾 Date&#xff1a;2024-06-25 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 类图 2. 代码解析 //***********************核心字段************************ // MarkupSegment起点坐标 double startX; double…

MySQL如何实现事务特性

目录 事务有那些特性 原子性如何实现 持久性如何实现 隔离性与一致性如何实现 事务有那些特性 事务是由MySQL的引擎 InnoDB 来实现的 事务的特性 : 原子性 不存在中间状态,要么完成,要么不完成 一致性 事务操作前和操作后,数据满足完整性的约束,数据库保持一致的状态…

mac鼠标和触摸屏单独设置滚动方向

引言&#xff1a;mac很好用&#xff0c;但是外接鼠标的滚动方向和win不一样&#xff0c;总有点不习惯。于是想要设置一下&#xff0c;当打开设置&#xff0c;搜索鼠标时&#xff0c;将“自然滚动”取消&#xff0c;就可以更改了。 问题&#xff1a;但触摸屏又不好用了。 原因&a…

VBA递归过程快速组合数据

实例需求&#xff1a;数据表包含的列数不固定&#xff0c;有的列&#xff08;数量和位置不固定&#xff09;包含组合数据&#xff0c;例如C2单元格为D,P&#xff0c;说明Unit Config有两种分别为D和P&#xff0c;如下图所示。 现在需要将所有的组合罗列出来&#xff0c;如下所示…

模块化沙箱结合零信任实现一机两用解决方案

为实现数据防泄露的各类型市场需求以及“一机两用”标准落地&#xff0c;依靠十几年的沙箱技术积累&#xff0c;研发出了支持多平台的模块化沙箱&#xff0c;配合零信任SDP网关&#xff0c;提高数据安全&#xff0c;实现“一机两用”安全解决方案。 产品特点 -自2008年开始已…

奇点临近:人类与智能时代的未来

在信息爆炸的时代&#xff0c;我们每天都被海量的信息所淹没&#xff0c;如何才能在这个嘈杂的世界中找到真正有价值的信息&#xff1f;如何才能利用信息的力量&#xff0c;提升我们的认知水平&#xff0c;重塑我们的未来&#xff1f; 这些问题的答案&#xff0c;或许都能在雷…