JavaWeb——后端之Mybatis

news2025/5/22 22:56:03

四、Mybatis

概念: Mybatis是一款持久层(Dao层)框架,用于简化JDBC(Sun操作数据库的规范,较繁琐)的开发

历史: Apache的一个开源项目iBatis,2010年由apache迁移到了google code,并改名MyBatis。2013年11月迁移到Github

1. 入门程序

1)创建Spring module;创建的时候勾选MyBatis Framework和MySql service(对应数据库的类型)

2)准备数据以及数据库环境

3)定义一个实体类,实体类的变量要与表中的数据类型以及名称对应,实体类变脸阿哥使用包装类,命名使用驼峰命名

4)创建Mybatis的环境,在模块的application.properties中声明

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://124.221.237.48(地址):3306/test(数据库名)
#连接数据库的用户名
spring.datasource.username=xy
#连接数据库的密码
spring.datasource.password=123456

5)定义mapper,就是使用Sql语句的类,要使用Mapper进行注解,这样运行时,会自动生成该接口的实现类对象(代理对象),并将该对象交给IOC容器管理。

在类中定义抽象方法,如果是查询就使用@Select()注解,括号中指定sql查询语句

注:要想有sql语法提示

选中Sql语句右键Show Context Actions——>inject language——>MySql(要想提示表名,要将数据库连接到IDEA——使用IDEA连接数据库)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这里插入图片描述

6)在测试启动类中编写测试方法,因为要使用mapper接口中的方法,所以使用Autowired,从IOC中获取bean对象

2. 数据库池连接

使用配置文件进行配置之后,SpringBoot底层就会自动使用数据库连接池技术管理和分配连接

概念:

  • 数据库连接池是个容器,负责分配、管理数据库连接
  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重建一个
  • 释放空闲时间超过最大空闲事件的连接,来避免因为没有释放连接而一起的数据库连接遗漏

优势:

  • 资源重用
  • 提升系统响应速度
  • 避免数据库连接遗漏

产品:

Druid

引入依赖(版本要对应调整)

# Spring2
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.2.8</version>
</dependency>

# Spring3
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid-spring-boot-3-starter</artifactId>
	<version>1.2.20</version>
</dependency>

配置数据库连接池类型(可以不)

Hikari(springboot默认)

3. lombok工具包

原有问题: 数据库中的数据要对应一个实体类,并为其生成构造器,getter/setter,toString等方法

lombok: 一个实用的java类库,能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发,提高效率

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

准备工作: 添加依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

注: Lombok会在编译时,自动生成对应的java代码。我们使用lombok时,还需要安装一个lombok的插件(idea自带)

4. Mybatis基础操作

1)删除

EmpMapper.java

@Mapper
public interface EmpMapper {
    // 根据ID删除数据
    @Delete("delete from emp where id= #{id}")
    public void delete(Integer id);
}
// #{}是占位符,生成的就是预编译的SQL语句

测试方法

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;
    @Test
    public void testDelete() {
        empMapper.delete(17);
    }
}

想要查看执行的日志信息可以配置==>预编译SQL

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

在这里插入图片描述

在这里插入图片描述

参数占位符

在这里插入图片描述

2)新增

接口方法

// 插入数据
@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);
    }

主键返回

插入数据成功后,想要获取这个插入数据的主键

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

3)更新

根据主键id查询回显

然后修改对应数据

@Update(更新的SQL语句)

4)查询

// 根据ID查询数据
@Select("select  * from emp where id = #{id}")
public Emp getById(Integer id);
@Test
public void testGetById() {
    Emp emp = empMapper.getById(1);
    System.out.println(emp);
}

在这里插入图片描述

数据封装

  • 实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装
  • 如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装(数据库属性命名是下划线分隔,实体类变量命名是驼峰)

解决数据封装问题

方案一:给数据库字段起别名

方案二:通过@Results,@Result注解手动映射封装

// 通过@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的驼峰命名自动映射开关(前提:数据库字段名字和Java中的属性名命名都是严格按照规范的)

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

条件查询

// 条件查询
//    @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> list(String name, Short gender, LocalDate begin, LocalDate end);
// 为了防止SQL注入
@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> list(String name, Short gender, LocalDate begin, LocalDate end);
@Test
public void testSelect() {
List<Emp> empList = empMapper.list("张", (short)1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
System.out.println(empList);
}

5. XML映射文件(配置SQL语句)

在这里插入图片描述

条件查询的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.itheima.mapper.EmpMapper">
    <!--第一个参数是方法名,第二个参数是查询返回的单条语句的全类名-->
    <select id="list" resultType="com.itheima.pojo.Emp">
        select * from emp where name like concat('%', #{name}, '%') and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc
    </select>
</mapper>

MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生

使用注解来映射简单的语句会使代码更加简洁,但是稍微复杂一点,就混乱不堪。——>如果做一些复杂的操作,最好使用XML来映射语句

6. 动态SQL

概念: 随着用户的输入或者外部条件的变化而变化的SQL语句

6.1 <if>

<mapper namespace="com.itheima.mapper.EmpMapper">
    <!--第一个参数是方法名,第二个参数是查询返回的单条语句的全类名-->
    <select id="list" resultType="com.itheima.pojo.Emp">
        select *
        from emp
        where
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
        order by update_time desc
    </select>

</mapper>
@Test
public void testSelect() {
    // List<Emp> empList = empMapper.list("张", (short)1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
    List<Emp> empList = empMapper.list("张", null, null, null);
    System.out.println(empList);
}

在这里插入图片描述

问题: 如果第一个为空,wher就会紧跟着and,不合规的SQL

解决: 使用<where></where> 代替where

  • 动态生成where关键字
  • 自动去除条件前的and和or
<mapper namespace="com.itheima.mapper.EmpMapper">
    <!--第一个参数是方法名,第二个参数是查询返回的单条语句的全类名-->
    <select id="list" resultType="com.itheima.pojo.Emp">
        select *
        from emp
        <where>
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and 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>

<set></set>

  • 去掉字段之后多余的逗号

6.2 <foreach>

<!--批量删除-->
<!--
collection:遍历的集合
item:遍历的元素
separator:分隔符
open:遍历开始前拼接的SQL片段
close:遍历结束后拼接的SQL片段
-->
<delete id="deleteByIds">
    delete from emp where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>
// 批量删除
public void deleteByIds(List<Integer> ids);
@Test
public void testDeletByIds() {
    List<Integer> ids = Arrays.asList(13, 14, 15);
    empMapper.deleteByIds(ids);
}

6.3 <sql><include>

重复SQL片段——》代码复用性差

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

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

相关文章

常见位运算总结

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 前言 1.基础位运算 &运算 |运算 ^运算 >>运算 <<运算 ~运算 2.给一个数n&#xff0c;确定他的二进制表示中的第x位&#xff0c;是0还是1 3.将一个数n的二进制表示的第x位修改成1 4.将一个数…

QML 项目中使用 Qt Design Studio 生成的UI界面

作者&#xff1a;billy 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 前言 今天来和大家聊一下 Qt Design Studio 这个软件。这个软件的主要功能是用来快速完成 UI 界面&#xff0c;就和 widget 中的 desig…

Redis学习笔记(1)——感谢尚硅谷官方文档

Redis学习笔记&#xff08;1&#xff09;——感谢尚硅谷官方文档 1. NoSQL1.1 NoSQL数据库概述1.2 各种NoSQL数据库 2. Redis数据库安装2.1 安装条件2.2 Widows下如何安装Redis?2.3 Linux下如何安装Redis? 3. Redis介绍3.1 Redis 简介3.2 Redis 优势3.3 Redis与其他key-value…

HttpClient库与代理IP在爬虫程序中的应用

目录 前言 一、HttpClient库的基本使用方法 二、代理IP的使用方法 三、代理IP池的使用方法 四、总结 前言 在编写爬虫程序时&#xff0c;我们经常会使用HttpClient库来发送HTTP请求&#xff0c;获取网页内容。然而&#xff0c;有些网站可能会对频繁的请求进行限制&#x…

python的课后练习总结3之条件语句

1,简单点&#xff0c;只有IF IF 后面加入条件然后冒号: 条件成立执行的代码1 条件成立执行的代码2 条件是否成立都执行的代码 身高 float(input(请输入你的身高(米):)) if 身高 > 1.3:print(f您的身高是{身高}米,请您买票) print(祝您旅途愉快) 2,IF 加个else if 条件:…

[论文分享]TimesURL:通用时间序列表示学习的自监督对比学习

论文题目&#xff1a;TimesURL: Self-supervised Contrastive Learning for Universal Time Series Representation Learning 论文地址&#xff1a;https://arxiv.org/abs/2312.15709 代码地址&#xff1a;暂无 摘要 学习适用于各种下游任务的通用时间序列表示具有挑战性&…

无人机低空视角:针对人群密集场景的检测、跟踪和计数技术

无人机低空视角&#xff1a;针对人群密集场景的检测、跟踪和计数技术 DroneCrowdPaper简介数据集ECCV2020挑战DroneCrowd&#xff08;完整版&#xff09; DroneCrowd Paper 无人机在人群中的检测、跟踪和计数&#xff1a;基准研究。 简介 本文提出了一种时空多尺度注意力网络…

数据结构与算法——第一次大作业【考点罗列//错题修正//题解】

目录 一、选择题 ——绪论—— 1.【单选题】——数据结构的研究方向 2.【单选题】 ——数据结构的研究问题 3.【单选题】——数据结构的基本术语及概念 4.【单选题】 ——数据结构与算法 5.【单选题】 ——时间复杂度计算 ——顺序表与链表—— 6.【单选题】——顺序表…

算法训练营Day36(贪心-重叠区间)

都算是 重叠区间 问题&#xff0c;大家可以好好感受一下。 都属于那种看起来好复杂&#xff0c;但一看贪心解法&#xff0c;惊呼&#xff1a;这么巧妙&#xff01; 还是属于那种&#xff0c;做过了也就会了&#xff0c;没做过就很难想出来。 不过大家把如下三题做了之后&#…

多通道病虫害分子检测仪-百科科普知识

在农业科技日新月异的今天&#xff0c;病虫害防治已经成为现代农业的重要一环。为了更精准、更快速地检测和防治病虫害&#xff0c;多通道病虫害分子检测仪应运而生&#xff0c;成为守护绿色家园的"黑科技"。 WX-XC1多通道病虫害分子检测仪是一款集成了分子生物学、…

音频DAC,ADC,CODEC高性能立体声

想要让模拟信号和数字信号顺利“交往”&#xff0c;就需要一座像“鹊桥”一样的中介&#xff0c;将两种不同的语言转变成统一的语言&#xff0c;消除无语言障碍。这座鹊桥就是转换器芯片&#xff0c;也就是ADC芯片。ADC芯片的全称是Analog-to-Digital Converter, 即模拟数字转换…

webpack知识点总结(高级应用篇)

除开公共基础配置之外&#xff0c;我们意识到两点: 1. 开发环境(modedevelopment),追求强大的开发功能和效率&#xff0c;配置各种方便开 发的功能;2. 生产环境(modeproduction),追求更小更轻量的bundle(即打包产物); 而所谓高级应用&#xff0c;实际上就是进行 Webpack 优化…

linux 系统 kill 指令笔记

kill 名称 kill - send a signal to a process 向指定的线程或进程发送信号 描述 The default signal for kill is TERM. Use -l or -L to list availablesignals. Particularly useful signals include HUP, INT, KILL, STOP,CONT, and 0. Alternate signals …

C#: 和时间相关,延时、获取系统时间、时间格式转换、定时器 等

说明&#xff1a;本文记录C# 和时间相关&#xff0c;延时、获取系统时间、时间格式转换、定时器 等&#xff0c;应用和代码。 1.延时函数 System.Threading.Thread.Sleep(20); //毫秒 1.1 主线程不卡延时函数 /* 主线程不卡延时函数 */public static void Delay_ms(int mil…

【C语言期末】基于VS2022的学生成绩管理系统

诚接计算机专业编程任务(C语言、C、Python、Java、HTML、JavaScript、Vue等)10/15R&#xff0c;如有需要请私信我&#xff0c;或者加我的企鹅号&#xff1a;1404293476 本文资源&#xff1a;https://download.csdn.net/download/weixin_47040861/88702521https://download.csd…

Spring Cloud Config相关面试题及答案(2024)

1、什么是 Spring Cloud Config&#xff0c;它解决了哪些问题&#xff1f; Spring Cloud Config 是一个为微服务架构提供集中化外部配置支持的项目。它是构建在 Spring Cloud 生态系统之上&#xff0c;利用 Spring Boot 的开发便利性&#xff0c;简化了分布式系统中的配置管理…

LCR 174. 寻找二叉搜索树中的目标节点

解题思路&#xff1a; 二叉搜索树一般采用中序遍历&#xff08;从小到大排列&#xff09;。 class Solution {int res, cnt;public int findTargetNode(TreeNode root, int cnt) {this.cnt cnt;dfs(root);return res;}void dfs(TreeNode root) {if(root null) return;dfs(ro…

利用蚁剑钓鱼上线CS

前言 ​ 中国蚁剑使用Electron构建客户端软件&#xff0c;Electron实现上用的是Node.js&#xff0c;并且Node.js能执行系统命令&#xff0c;故可以利用蚁剑的webshell页面嵌入js来直接执行命令&#xff0c;进而钓鱼来上线CS。&#xff08;类似Goby&#xff0c;Goby也是使用Ele…

Vue2 - diff 原理(动图演示)

目录 1&#xff0c;diffdiff 的时间点 2&#xff0c;_update 函数3&#xff0c;_patch 函数&#xff08;进行 diff&#xff09;3.1&#xff0c;根节点比较3.2&#xff0c;子节点比较 4&#xff0c;key的问题举例1举例2 1&#xff0c;diff 解释&#xff1a;对比新旧虚拟DOM树&a…

杨中科 ASP.NETCore开发效率利器 HOT RELOAD

HOT RELOAD 1、困惑:修改了服务器端的代码&#xff0c;必须重新运行程序。 2、方法1: [启动 (不调试) ] 3、方法2: .NET 6开始的Hot Reload(热重载) 正常修改代码后 不重启&#xff0c;是无法看到新的数据展示在页面 修改 运行结果&#xff1a; 方式一&#xff1a;设置开始…