《JavaEE进阶》----16.<Mybatis简介、操作步骤、相关配置>
本篇博客讲记录:
1.回顾MySQL的JDBC操作
2..Mybatis简介、Mybatis操作数据库的步骤
3.Mybatis 相关日志的配置(日志的配置、驼峰自动转换的配置)
前言
之前学习应用分层时我们知道Web应用程序一般分为三层,Controller、Service、Dao。
浏览器发起请求、现请求Controller、Controller接收到请求后,调用Service进行业务逻辑处理。Service再调用Dao。Dao再从数据库中获取数据。今天我们就来讲解Mybatis数据库。
学习MySQL数据库时,已经学习了JDBC来操作数据库。而JDBC操作很复杂。这就是我们要学习 MyBatis 的真正原因,它可以帮助我们更方便、更快速的操作数据库。Mybatis就是对JDBC封装后的结果。
一、JDBC操作示例回顾:
JDBC操作步骤
1. 创建数据库连接池DataSource
private final DataSource dataSource;public SimpleJdbcOperation(DataSource dataSource) {this.dataSource = dataSource;}
2. 通过DataSource获取数据库连接Connection
public void addBook() {Connection connection = null;PreparedStatement stmt = null;try {//获取数据库连接 connection = dataSource.getConnection();
3. 编写要执行带?占位符的SQL语句(预编译SQL)(不能封装)
//创建语句 stmt = connection.prepareStatement("insert into soft_bookrack (book_name, book_author, book_isbn) values (?,?,?);");
4. 通过Connection及SQL创建操作命令对象Statement
PreparedStatement stmt = null;
5. 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值(不能封装)
//参数绑定 stmt.setString(1, "Spring in Action");stmt.setString(2, "Craig Walls");stmt.setString(3, "9787115417305");
6. 使用Statement执行SQL语句
//执⾏语句 stmt.execute();
7. 查询操作:返回结果集ResultSet,更新操作:返回更新的数量
//执⾏语句 rs = stmt.executeQuery();if (rs.next()) {book = new Book();book.setName(rs.getString("book_name"));book.setAuthor(rs.getString("book_author"));book.setIsbn(rs.getString("book_isbn"));}System.out.println(book);
8. 处理结果集
} catch (SQLException e) {//处理异常信息
9. 释放资源
} finally {//清理资源 try {if (stmt != null) {stmt.close();}if (connection != null) {connection.close();}} catch (SQLException e) {//}}
由于使用JDBC时,太多内容重复操作,并且步骤繁琐。为了更加方便我们操作数据库。我们对这些非个性化的步骤进行封装。因此Mybatis就诞生了。
①如果Mybatis字段和Java属性一样,Mybatis会自动进行赋值,对于不一样的字段,需要我们告诉Mybatis,字段和属性的映射关系。
最终我们发现只有第三条和第五条是需要我们手动操作的。其他的一切都有规律可循。因此我们将其他步骤进行封装,只留一个接口让你去填SQL语句和赋值的参数。其他Mybatis都帮你搞定。
-- 创建数据库
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 操作的具体实现代码:
package com.example.demo.mapper;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
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) {//}}
}/*** 更新⼀本书 */public void updateBook() {Connection connection = null;PreparedStatement stmt = null;try {//获取数据库连接 connection = dataSource.getConnection();//创建语句 stmt = connection.prepareStatement("update soft_bookrack set book_author=? where book_isbn=?;");//参数绑定 stmt.setString(1, "张卫滨");stmt.setString(2, "9787115417305");//执⾏语句 stmt.execute();} catch (SQLException e) {//处理异常信息 } finally {//清理资源 try {if (stmt != null) {stmt.close();}if (connection != null) {connection.close();}} catch (SQLException e) {//}}}/*** 查询⼀本书 */public void queryBook() {Connection connection = null;PreparedStatement stmt = null;ResultSet rs = null;Book book = null;try {//获取数据库连接 connection = dataSource.getConnection();//创建语句 stmt = connection.prepareStatement("select book_name, book_author, book_isbn from
soft_bookrack where book_isbn =?");//参数绑定 stmt.setString(1, "9787115417305");//执⾏语句 rs = stmt.executeQuery();if (rs.next()) {book = new Book();book.setName(rs.getString("book_name"));book.setAuthor(rs.getString("book_author"));book.setIsbn(rs.getString("book_isbn"));}System.out.println(book);} catch (SQLException e) {//处理异常信息 } finally {//清理资源 try {if (rs != null) {rs.close();}if (stmt != null) {stmt.close();}if (connection != null) {connection.close();}} catch (SQLException e) {//}}}public static class Book {private String name;private String author;private String isbn;//省略 setter getter ⽅法 }
}
二、什么是Mybatis?
MyBatis是一款优秀的持久层框架,用于简化JDBC的开发。
MyBatis本是Apache的⼀个开源项目iBatis,2010年这个项目由apache迁移到了googlecode,并 且改名为MyBatis。2013年11月迁移到Github。
Mybatis官网:https://blog.mybatis.org
Mybatis中文网:MyBatis中文网
持久层:指的就是持久化操作的层,通常指数据访问层(dao),是用来操作数据库(DB)的.
简单来说MyBatis是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库工具 接下来,我们就通过⼀个入门程序,让大家感受下一通过Mybatis如何来操作数据库
Mybatis操作数据库的步骤:
1.准备工作:创建Springboot工程、数据库表准备、实体类
2.引入Mybatis相关依赖(Mybatis Framework、Mysql Drive)、配置Mybatis数据库连接信息。
3.编写SQL语句(注解/XML)
4.测试
配置Mybatis。
我们使用配置文件application.yml类型的文件进行配置。配置代码如下
驼峰自动转换就可以让我们在数据库中存在的映射关系进行匹配成功
例如字段
delete_flag → deleteFlag
create_time →createTime
updata_time →updataTime
此时数据库的字段名称就可以与我们在实体类创建的成员属性相匹配,这样打印出来的有分割的类似这种数据库表字段updata_time 就可以被识别打印了 而不是打印的null。
三、Mybatis在IDEA中的操作方法:
3.1 第一步:准备工作(创建springboot工程、数据库表准备、实体类)
3.1.1创建springboot工程
首先创建SpringBoot项目。选择Maven来管理项目。选择Mybatis Framework,MySQL Driver等依赖。在项目左侧的数据库栏添加配置数据库。并新建表,创建已经准备好的数据库表。
Mybatis是一个持久层框架,具体的数据存储和数据操作还是在MySQL中操作的,所以需要添加 MySQL驱动
3.1.2数据库表准备
如我们现在要创建一个用户表,并要创建对应的实体类
建表规范
常见规范:
1.字段全部小写,单词之间使用_分割(数据库的字段修改代价非常大,数据量很大!)
2.建表需要具备三个字段,哪怕你不用 (id create_time updata_time)
使互联网上有迹可循
delete_flag删除标志(1.逻辑删除(企业)(通过更新),2.物理删除(delete))
create_time updata_time 这两个字段使用Data类型是因为这个类型保存的时间是非常细节的,可以细致到时分秒。
--创建数据库 DROP DATABASE IF EXISTS mybatis_test; CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;-- 使用数据数据 USE mybatis_test;-- 创建表 [ 用户表 ] DROP TABLE IF EXISTS userinfo; 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' );
3.1.3对应的实体类
配置好数据库之后,在Idea中创建一个实体类。对应数据库表中的元素
对应的实体类
实体类的属性名与表中的字段名⼀⼀对应
注意Data类型是java.util包下面的,代表的是时间日期。
3.2 第二步:引入Mybatis的相关依赖
引入Mybatis的相关依赖
引入的依赖就是上面我们选择的Mybatis Framework,MySQL Driver等依赖。在pom.xml文件中,我们会看到我们引入的依赖信息;
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version> </dependency> <dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope> </dependency>
若我们在选择依赖的时候忘了选择,我们可以在pom.xml文件中右键,点击第一个选项,我们之前下载好的插件。从这里我们可以继续选择依赖。
3.1.3 配置数据库连接字符串
①使用配置文件
配置文件代码如下
注:当引入了Mybatis框架,就一定要进行配置文件,需要配置数据库链接。负责服务就不会正常启动,就会报错。
# 数据库连接配置
spring:datasource: url: jdbc:mysql://127.0.0.1:3306/mybatis_test? characterEncoding=utf8&useSSL=falseusername: root password: rootdriver-class-name: com.mysql.cj.jdbc.Driver
说明
- url: 数据库的 JDBC 连接 URL。请确保 IP 地址、端口号、数据库名称以及连接参数正确。
- username: 数据库用户名称(默认为root)。
- password: 数据库用户密码(这个是安装MySQL的时候设置的密码)。
- driver-class-name: 使用的 JDBC 驱动类,这里指定
com.mysql.cj.jdbc.Driver
是 MySQL 8.x 使用的驱动类url: jdbc:mysql://127.0.0.1:3306/mybatis_test? characterEncoding=utf8&useSSL=false
这个url中
jdbc: 表示Java Database Connectivity (JDBC)API进行数据库链接。
mysql:指定要连接的数据库类型为mysql
127.0.0.1:3306:这是数据库服务器的IP地址和端口号
mybatis_test:数据库名称(要确保这个数据库已经在MySQL服务器上面创建)
?:?后面这是;连接参数部分,以?开始,多个参数用&分隔。
characterEncoding=utf8&useSSL=false:设置字符编码为
UTF-8、
指定不使用 SSL 加密连接。
注:
配置好了之后就可以直接访问数据库了。不过为了更直观的看到数据库中的信息。我们通常不会通过MySQL来操作。
1.我们可以使用数据库管理工具Navicat Premium来管理我们的数据库。
2.我们也可以不用配置文件。直接在IDEA中自带的数据库中直接添加数据源。
②不使用配置文件
直接在IDEA中自带的数据库中直接添加数据源。选择MySQl。
输入名称、用户名、密码、数据库名称点击确定。这样数据库就被导入进来了。
我们可以右键这个数据库来创建表。复制我们之前准备好的数据。粘贴进去点击确定。表就被创建好了
3.3 第三步:编写SQL语句(注解/XML)
为了避免标题级别过多,文章内容过多。我们将这一步放在下一篇文章来详细说明。
3.4 第四步:测试
测试实际上很简单,只需要在我们添加了注解的SQL语句右侧右键,点击生成。再点击测试即可。
我们点击测试, 我们就会进入UserInfoMapperTest这个类。
/*** 是开发人员的自测代码*/
//上面的三角运行是执行所有的Test方法
@Slf4j
@SpringBootTest //帮助我们加载Spring的运行环境
class UserInfoMapperTest {@Autowired//private UserInfoMapper userInfoMapper;//注入Mapper@BeforeEachvoid setUp() {//表示Test方法执行前执行log.info("setUp...");} //执行Test方法前执行@AfterEachvoid tearDown() {//表示Test方法执行后执行log.info("tearDown...");} //执行Test方法后执行// 下面的三角运行符号表示执行当前Test方法@Testvoid queryUserList() {log.info(userInfoMapper.queryUserList().toString());}
}
报错
这是SQL语句出错、检查SQL语句就好了。
四、Mybatis相关配置文件
4.1配置Mybatis打印日志
mybatis:configuration: # 配置打印 MyBatis⽇志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
配置后Mybatis日志。多了如下内容,更加方便我们查看数据库。这是MySQL
返回的结果。
对通过注解+SQL语句查的补充:驼峰转换
虽然我们编写了如下关于查的相关SQL语句,在MySQL放回的结果中我们可以看到delete_flage,create_time,update_time的值,但是通过Mybatis查询的结果并没有这些值,这是为什么呢?因为MySQL中的字段名是delete_flage,create_time,update_time带有分隔符,而在实体类中我们写的是deleteFlag,createTime,updateTime是不一样的。因此Mybatis并没有访问到MySQL中的相对应字段值。如何解决这个问题呢?有三种办法。
三种办法解决deleteFlag,createTime,updateTime为null
1.改别名
2.通过注解来映射
(也可以复用通过@ResultMap注解,@ResultMap(value = “BaseResult”))
4.2 第三种:配置自动驼峰的转换
将下文添加到配置文件application.yml中,代码不做任何处理
mybatis:configuration:map-underscore-to-camel-case: true # 配置驼峰自动转换
相关文章:

《JavaEE进阶》----16.<Mybatis简介、操作步骤、相关配置>
本篇博客讲记录: 1.回顾MySQL的JDBC操作 2..Mybatis简介、Mybatis操作数据库的步骤 3.Mybatis 相关日志的配置(日志的配置、驼峰自动转换的配置) 前言 之前学习应用分层时我们知道Web应用程序一般分为三层,Controller、Service、D…...

HuggingFists算子能力扩展-PythonScript
HuggingFists作为一个低代码平台,很多朋友会关心如何扩展平台算子能力。扩展平台尚不支持的算子功能。本文就介绍一种通过脚本算子扩展算子能力的解决方案。 HuggingFists支持Python和Javascript两种脚语言的算子。两种语言的使用方式相同,使用者可以任选…...

WInform记录的添加和显示
1、程序 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace ComboBoxApp {public part…...

★ C++基础篇 ★ string类的实现
Ciallo~(∠・ω< )⌒☆ ~ 今天,我将继续和大家一起学习C基础篇第五章下篇----string类的模拟实现 ~ 上篇:★ C基础篇 ★ string类-CSDN博客 C基础篇专栏:★ C基础篇 ★_椎名澄嵐的博客-CSDN博客 目录 一 基础结构 二 迭代器 …...

rman compress
级别 初始 备完 耗时 low 1804 3572 0:10 High 1812 3176 2:00 MEDIUM 1820 3288 0:13 BASIC 1828 3444 0:56 ---不如MEDIUM,时间还长 NO COMPRESS 1820 5924 0:5 R…...

创建一个Oracle版本的JDK的Docker镜像
背景说明 OpenJDK 和Oracle JDK 一般情况下我们选择OpenJDK,两者针对大部分场景都可以满足,有些地方例如反射技术获得某些包路径下的类对象等,有时候选择OpenJDK会导致空指针异常。 两者在底层实现方面有部分区别。 创建镜像 这里是Linux…...

Harmony OS DevEco Studio 如何导入第三方库(以lottie为例)?-- HarmonyOS自学2
在做鸿蒙开发时,离不开第三方库的引入 一.有哪些支持的Harmony OS的 第三方库? 第三方库下载地址: 1 tpc_resource: 三方组件资源汇总 2 OpenHarmony三方库中心仓 二. 如何加入到DevEco Studio工程 以 lottie为例 OpenHarmony-TPC/lot…...

JAVA数据导出为Excel
目录 一、导入依赖 二、使用的相关类 1、XSSFWorkbook 构造方法 创建表 操作表 保存表 样式和格式 日期处理 密码保护 其他 2、XSSFSheet 获取属性和信息 行操作 列操作 表的属性 合并单元格 保护表 页眉和页脚 注释 其它 3、XSSFRow 获取属性和信息 单…...

【数据结构与算法 | 灵神题单 | 快慢指针(链表)篇】力扣876, 2095, 234
1. 力扣876:链表的中间节点 1.1 题目: 给你单链表的头结点 head ,请你找出并返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。 示例 1: 输入:head [1,2,3,4,5] 输出:[3,4,…...

第十五届蓝桥杯图形化省赛题目及解析
第十五届蓝桥杯图形化省赛题目及解析 一. 单选题 1. 运行以下程序,角色会说( )? A、29 B、31 C、33 D、35 正确答案:C 答案解析: 重复执行直到m>n不成立,即重复执行直到m<n。所有当m小于或者 等于n时&…...

linux下NTP服务器实战(chrony软件)
linux下NTP服务器实战(chrony软件) 记录linux下NTP服务器搭建及相关管理操作,使用chrony软件包安装部署。相比ntp服务,Chrony服务适用于更高精度、更高稳定性、自动化等场景。 1. 安装 chrony 在大多数Linux发行版上,chrony可以通过包管理…...

Java设计模式之命令模式介绍和案例示范
一、命令模式简介 命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为一个对象,从而使你可以用不同的请求对客户端进行参数化、对请求排队或记录日志,以及支持可撤销的操作。命令模式的核心思想是将发出请…...

Leetcode面试经典150题-74.搜索二维矩阵
解法都在代码里,不懂就留言或者私信 二分查找,比较简单 class Solution {/**解题思路:每一行有序、每一列也有序,只是整体不是严格有序的,那我们需要找一个点,只能往两个方向走,往一个方向走是…...

【数字集成电路与系统设计】基本的组合逻辑电路
目录 一、简单例子引入 1.1 端口声明 1.1.2 Verilog实现 1.1.3 Chisel实现 逐行解释 1.2 内部逻辑实现 1.2.1 Verilog实现 1.2.2 Chisel实现 Chisel 关键点解释 1.3 常用的硬件原语 二、Chisel主要数据类型介绍 2.1 数据类型 2.2 数据宽度 2.3 数据转换 2.4 运算…...

11. 建立你的第一个Web3项目
11. 建立你的第一个Web3项目 在这一部分,我们将带你一步步地建立一个简单的Web3项目,从环境搭建到智能合约的创建与部署,再到开发一个去中心化应用(dApp)并与智能合约交互。这是你迈向Web3开发的第一步。 1. 环境搭建…...

衡石分析平台使用手册-容器部署
容器部署 本文介绍如何在容器上部署 HENGSHI SENSE,以及部署后如何进行版本升级和数据备份。 部署前准备工作 单机部署前,请完成如下准备工作。 1.检查 docker 的环境。需要满足 Docker 版本 > 17.09安装 docker-compose。 2.获取并导入离线…...

静态库,动态库以及makefile基础
一.静态(链接)库 libfun.a 静态链接进可执行程序 可执行程序偏大 运行时只需要可执行程序即可 生成静态库步骤 gcc -c fun.c -o fun.o ar rcv libfun.a fun.o //需要用.o文件生成数据库 运行 gcc main.c libfun.a 二.动态库 libfun.so 动…...

Python基础语法(1)上
常量和表达式 我们可以把 Python 当成一个计算器,来进行一些算术运算。 print(1 2 - 3) print(1 2 * 3) print(1 2 / 3) 这里我们可能会有疑问,为什么不是1.6666666666666667呢? 其实在编程中,一般没有“四舍五入”这样的规则…...

使用 Python/java/go做一个微信机器人
E云是一套完整的的第三方服务平台,包含微信API服务、企微API服务、SCRM系统定制、企微系统定制、服务类软件定制等模块,本文档主要讲述个微API服务相关,以下简称API,它能处理用户微信中的各种事件,提供了开发者与个微对…...

【北京迅为】iTOP-i.MX6开发板使用手册第四部分固件编译第十四章非设备树Android4.4系统编译
可根据用户需求更换,百变定制,高端产品无忧! 迅为IMX6Q兼容四核商业级 、双核商业级、四核工业级 、更可提供i.MX6Q家族PLUS版本核心板。 核心板采用十层PCB沉金盲埋设计,更能保证电磁兼容与系统稳定。 公众号:迅为电…...

测评造假?Mistral首个多模态模型Pixtral 12B发布
测评造假?Mistral首个多模态模型Pixtral 12B发布! 近日,法国人工智能(AI)初创公司Mistral于9月11日宣布推出其首款多模态AI大模型——Pixtral 12B,成功吸引了全球科技界的广泛关注。这款集图像与文本处理能…...

【Java-简单练习题】
1.”AABBBCCC“>>"A2B3C3" public class Test6 {public static void main(String[] args) {String ns "AABBBCCCC";String retcompress(ns);System.out.println(ret);}public static String compress(String str) {StringBuilder ret new StringB…...

Notepad++ 下载安装教程
目录 1.下教程 2.安装教程 1.下教程 Downloads | Notepad (notepad-plus-plus.org) 进入下载地址后选择最新版点击连接 点击链接后,向下滑动,下载适合自己电脑版本的安装包 这里大家没有梯子可能打不开页面,可以直接从本文开头下载。 2.安…...

shader 案例学习笔记之smoothstep函数
参考:smoothstep 用来生成0-1的平滑过渡值 smoothstep函数源码实现: float smoothstep(float t1, float t2, float x) {// Scale, bias and saturate x to 0..1 rangex clamp((x - t1) / (t2 - t1), 0.0, 1.0); // Evaluate polynomialreturn x * x *…...

大模型的第一个杀手级应用场景出来了
大家终于都意识到大模型首先改变的是软件行业自己,而软件的根基是代码生成。代码生成第一波就是AI辅助开发,这个会是大模型第一个杀手级应用。大家苦苦逼问自己的大模型杀手级应用,为什么会是辅助编程,这里说下什么: 必…...

不允许有程序员不知道这款AI代码扩写工具
01CodeGeeX编程大模型 在介绍什么是codeGeeX之前,先上图。 想象一下,自己写代码的时候旁边有个专家助手,随时跟你解释前面别人写的代码是什么意思,有什么缺陷。在你自己写的时候也可以每一步进行代码提示和代码扩写,是…...

java 的list集合排序自定义元素
在 Java 中,可以对包含自定义元素的List集合进行排序。通常可以使用Collections.sort()方法结合自定义的比较器来实现。 一、定义包含自定义元素的类 假设我们有一个表示学生的类Student: class Student {private int id;private String name;private …...

【数学建模】2024数学建模国赛经验分享
文章目录 一、关于我二、我的数模历程三、经验总结: 一、关于我 我的CSDN主页:https://gxdxyl.blog.csdn.net/ 2020年7月(大二结束的暑假)开始在CSDN写作: 阿里云博客专家: 接触的领域挺多的ÿ…...

Scala尾递归解决爆栈问题
引言 我在上篇中详细的讲了递归的一系列问题,多路递归,爆栈问题,尾递归优化等,今天就实际演示一下尾递归是如何解决爆栈问题的,以及它的原理是什么? 支持尾递归优化的语言 尾递归是一种特殊的递归形式,如果…...

【观察者】设计模式:构建灵活且响应式的软件系统
引言 在软件开发中,我们经常面临需要在多个对象之间进行通信的挑战。特别是当一个对象的状态发生变化时,我们希望所有依赖于这个状态的对象都能自动更新。这就是观察者设计模式大显身手的地方。 简介 观察者模式是一种行为设计模式,它定义…...