Fei

非淡泊无以明志,非宁静无以致远

实体关系图(ERD)指南

什么是实体关系图(ERD)?

数据库是软件系统中不可或缺的一个组成部分,若能在数据库工程中好好利用 ER 图,便能让您生成高质量的数据库设计,用于数据库创建,管理和维护,也为人员间的交流提供了具意义的基础。

本文将深入介绍 ER 图表。通过阅读本ERD指南,您将获得有关 ER 图和数据库设计的基本知识和技能。你会学到什么是 ERD,为什么要绘制 ERD,ERD 符号,如何绘制 ERD 等,以及一堆 ERD 示例

实体关系图也被称为 ERD、ER 图、实体联系模型、实体联系模式图或 ER 模型,是一种用于数据库设计的结构图。一幅 ERD 包含不同的符号和连接符,用于显示两个重要的信息: 系统范围内的主要实体,以及这些实体之间的相互关系。

什么是实体?

当我们谈论 ERD 中的实体时,我们经常提到诸如人员/角色(例如学生),有形商业对象(例如产品),无形商业对象(例如日志)等业务对象。“关系”則是这些实体在系统内的相互关联。

在典型的 ER 设计中,可以找到诸如圆角矩形和 (Rounded rectangle) 连接符(具有不同样式的末端)的符号来描述实体,它们的属性和相互关系。

ERD 的符号有哪些?

何时绘制ER图?

SSM

SSM三者的关系

1 Spring IoC容器

父子工程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.learning.springmvc</groupId>
<artifactId>ssm</artifactId>
<version>1.0-SNAPSHOT</version>

<!--父工程定义了版本, 子模块不需要再定义版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<!--父项目-->
<!--父项目一般不写代码-->
<!--适用场景:
1. 组织和管理多个子模块的公共配置(如依赖、插件、构建配置)。
2. 聚合子模块,使它们可以通过 mvn install 或 mvn package 一次性构建所有子模块。
3. 父项目自身没有具体的功能实现,仅作为管理和继承的基础。-->

<!--通常情况下,父项目的打包方式是 pom,这是最佳实践-->
<!--当父项目的打包方式为 pom 时,父项目本身不会生成实际的可部署包(如 jar 或 war),而仅作为一个配置聚合的容器-->
<packaging>pom</packaging>
<modules>
<module>ssm-spring-ioc</module>
</modules>

<!--当父工程要统一管理依赖时, 使用<dependencyManagement>进行管理, 子模块引用时, 不用再指定版本-->
<!--<dependencyManagement>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
</dependency>
</dependencies>
</dependencyManagement>-->

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

</project>

1.1 组件到容器

注册组件的方式:

  1. 使用@Import注解标识启动类
1
2
3
4
5
6
7
@Import({Dog.class, Person.class})
@SpringBootApplication
public class Application {
public static void main(String[] args) {
//1. 跑起一个Spring的应用, 获取一个ApplicationContext, 即ioc容器
ConfigurableApplicationContext ioc = SpringApplication.run(Application.class, args);
}

SpringMVC

Demo代码

1 SpringMVC 简介

MVC是一种软件架构思想, 将软件按照模型、视图、控制器来划分
M: Model : 模型层, 指工程中的Java Bean, 作用是处理数据
Java Bean分为两类:

  • 实体类Bean: 专门存储业务数据的, 比如User, Student
  • 业务处理Bean: 指Service或者Dao, 专门用于处理业务逻辑和数据访问

V: View :视图层, 指工程中html或sp等页面, 作用是与用户进行交互, 展示数据
C: Controller : 控制层, 指工程中的servlet, 作用是接受请求和响应浏览器

SpringMVC是一个Spring的子项目, SpringMVC有如下特点:

  • Spring系列原生产品, 与IOC容器等基础设施无缝对接
  • 基于原生的Servlet, 通过功能强大的前端控制器DispatcherServlet, 对请求和响应进行统一处理
  • 表述层各细分领域需要解决的问题全方面覆盖, 提供全面解决方案
  • 代码清晰简洁、组件化程度高、可插拔式组件即插即用、性能卓越..

2. HelloWorld

Spring

Demo代码

1 概述

Spring是一款主流的Java EE轻量级开源框架

  • 广义的Spring
    泛指以Spring Framework为核心的Spring技术栈, 如: Spring Framework, Spring MVC, SpringBoot, SpringCloud, SpringData, Spring Security, 其中Spring Framework是其他子项目的基础.

  • 狭义的Spring
    特指Spring Framework, 通常称为Spring框架. Spring框架是一个分层的、面向切面的java应用程序的一站式轻量级解决方案, 它是Spring技术栈的核心和基础, 是为了解决企业级应用开发的复杂性而创建的.
    Spring有两个核心模块, IoC和AOP.
    IoC: Inverse of Control: 控制反转, 指把创建对象的过程交给Spring进行管理
    AOP: Aspect Oriented Programing: 面向切面编程. AOP用来封装多个类的公共行为, 将那些与业务无关, 却为业务模块所共同调用的逻辑封装起来, 减少系统的重复代码, 降低模块间的耦合度. 另外, AOP还解决了一些系统层面的问题, 比如日志、事务、权限等.

1.1 Spring Framework特点

  • 非侵入式: 使用Spring Framework开发应用时, Spring对应用程序本身的结构影响非常小, 对领域模型可以做到零污染; 对功能性组件也只需要使用几个简单的注解进行标记, 完全不会破坏原有结构, 反而能将组件结构进一步简化. 这就让Spring Frame开发应用程序时结构清晰, 简洁优雅.
  • 控制反转: 框架创建对象
  • 面向切面: 在不修改源代码的基础上增强代码功能
  • 容器: Spring IoC是一个容器, 包含并管理组件对象的生命周期
  • 组件化: Spring实现了使用简单的组件配置组合成一个复杂的应用, 在Spring中可以使用xml和注解组合这些对象
  • 一站式: 可以整合各种开源框架

1.2 Spring模块组成

image-20251123091800267

1. 简单

1.1 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]


提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案


进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// O(n^2)
//按照距离寻找
//相邻, 间隔一位, 间隔二位, 间隔三位....
//01, 12,23,34,45,56....
//02, 13, 24, 35....
class Solution {
public int[] twoSum(int[] nums, int target) {
for(int i = 1; i < nums.length; i++){
for(int j = i; j < nums.length; j++){
if(nums[j-i] + nums[j] == target){
return new int[]{j-i, j};
}
}
}
return new int[]{0,0};
}
}


//哈希表
//注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。
// 使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到 O(1)。
// 这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。
// 时间复杂度:O(N),其中 N 是数组中的元素数量。对于每一个元素 x,我们可以 O(1) 地寻找 target - x。
// 空间复杂度:O(N),其中 N 是数组中的元素数量。主要为哈希表的开销。

class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i]; // 寻找 target - x
if (map.containsKey(complement)) { // 如果存在,返回索引
return new int[] { map.get(complement), i };
}
map.put(nums[i], i); // 将 x 插入哈希表
}
throw new IllegalArgumentException("No two sum solution");
}
}

1.2 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

今天哥们又接到一个文件处理的开发需求,要实现一个文件上传、下载的通用服务。为了快速满足这一需求,我使用了SpringBoot + 华为云OBS快速写了一个小小的程序。

项目结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
src
└── main
├── java
│   └── com
│   └── xmbc
│   └── file
│   ├── XmbcFileApplication.java # 启动类
│   ├── config
│   │   ├── HuaweiObsConfig.java # 华为云OBS的配置 (1)
│   │   └── ResourcesConfig.java
│   ├── controller
│   │   ├── HuaweiObsFileController.java # 文件上传下载的Controller (4)
│   │   └── SysFileController.java
│   ├── service
│   │   ├── ISysFileService.java # 文件处理的接口 (2)
│   │   └── impl
│   │   ├── FastDfsSysFileServiceImpl.java
│   │   ├── HuaweiObsSysFileServiceImpl.java # 华为云OBS的实现 (3)
│   │   └── LocalSysFileServiceImpl.java
│   └── utils
│   └── FileUploadUtils.java
└── resources
├── application-dev.yaml # 若依的框架原配置,没啥用,当个备份吧
├── application-local.yaml # 本地配置
├── banner.txt # 默认的logo
├── bootstrap.yaml # 启动类
└── logback.xml # 日志配置
12 directories, 15 files

好吧,大佬一看就知道这是使用了某个开源的框架,本文使用了若依的框架(对应ruoyi-file)。因为本文作者是个程序菜鸟,为了快速满足开发组长的需求,所以使用起来比较粗糙。

首先,看看我做了什么好事。在bootstrap.yamlapplication-local.yaml中配置好参数,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# bootstrap.yaml
spring:
profiles:
active: local

# application-local.yaml

server:
port: 9300
spring:
profiles:
activate:
on-profile: local
application:
name: xmbc-file
cloud:
nacos:
discovery:
enabled: false # 禁用nacos
obs:
huawei:
bucketName: test-xcmg-app-fileprocessing # 华为云OBS的bucket名称
endPoint: https://obs.cn-east-3.myhuaweicloud.com # 华为云OBS的endpoint

file: # 先随便乱写的,为了保证config可以读取,这里随便写一个。后续有需要再修改
path: "/"
prefix: "xmbc_file"
domain: "local.xmbc.com"

启动配置完成之后,我们就根据我上文的目录结构后注释的编号来看看对应的代码:

(1) HuaweiObsConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.xmbc.file.config;

import com.obs.services.ObsClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* Minio 配置信息
*
* @author xmbc
*/
@Configuration
@ConfigurationProperties(prefix = "obs")
@Data
public class HuaweiObsConfig
{
/**
* endpoint填写桶所在的endpoint
*/

@Value("${obs.huawei.endPoint}")
String endPoint;



/**
* 华为云Access Key
*/
private String accessKey = System.getenv("HUAWEICLOUD_SDK_AK");

/**
* 华为云Secret Key
*/
private String secretKey = System.getenv("HUAWEICLOUD_SDK_SK");

/**
* 存储桶名称
*/
@Value("${obs.huawei.bucketName}")
private String bucketName;


/**
* 创建ObsClient实例
* 使用永久AK/SK初始化客户端
*/
@Bean
public ObsClient getHuaweiObsClient()
{
return new ObsClient(accessKey, secretKey,endPoint);
}
}

1. 目的

说到目的,我现在学习技术的目的已经不再单纯的是因为着迷于技术本身,而是为了生活,过去两年的职业生活,让我逐渐意识到经济基础才能决定上层建筑。我的想法很丰富,想去遨游世界,想当老板,想成为一个技术大佬,想做个歌手… 而这些都好遥远啊,现在的我只能作为一个小小的打杂人员游离于这个社会之中,没有稳定的社交圈,没有自己的稳定居所,只有一份不上不下的工作维持这糟糕的生活。但是我不想这样下去,我想去成都找一份工作,能支撑我有一间自己的稳定居所,有自己的社交圈,不用现在每天提心吊胆,担心裁员,被孤独和焦虑折磨。 所以,所以这一次我重新安排自己的技术学习路线就是为了自己未来有一份稳定可观的工作,最好是在成都,这是我的目标,现在就这么确定好了。我会努力的!加油!

2. 技术学习路线

参考课程:
1.尚硅谷课程

按照自研项目的顺序进行学习。这个顺序也是一般应用部署的工作流程,所以对于记忆也更方便。

  • 自研项目:

    1. 基础设施: Linux
    2. 运行环境: Kubernetes, Docker
    3. 后端:
      1. SpringBoot, SpringCloud
      2. Flowable
      3. PostgreSQL or MySQL
    4. 前端:
      1. Vue
      2. Vue Element Admin
    5. 中间件: RabbitMQ, Nacos, Zookeeper, ElasticSearch, Nginx, Redis
  • 操作系统

    1. Linux – 巩固
  • 语言:

    1. Java – 巩固
    2. Python – 保持
    3. Go – 有时间去学习
  • 数据库:

    1. postgresql – 有时间去学习
    2. mysql – 巩固
    3. redis – 必学
  • 云原生:

    1. Kubernetes – 必学
    2. Docker – 巩固
  • 前后端框架:

    1. SpringBoot – 巩固
    2. SpringCloud – 专业学习
    3. Vue – 专业学习
  • 中间件:

    1. RabbitMQ – 必学
    2. Nacos – 必学
    3. Zookeeper – 必学
    4. ElasticSearch – 必学
    5. Nginx – 必学
    6. Redis – 必学
  • 开源项目:
    前端: Vue Element Admin – 必学
    后端: Flowable – 必学

3. 心路历程

2024-09-06: 又一次准备开始,这一次没有以前的那种强烈的斗志,不知道能坚持到什么时候,但是我必须得这么做,为了自己能在一两年内转到成都找一份收入可观的工作,我要努力💪。加油吧!!

Introduction

虽然“容器是Linux”,但Podman也可以在Mac和Windows上运行,它提供了一个原生的Podman CLI,并嵌入了一个客户Linux系统来启动您的容器。此访客被称为Podman机器,并使用Podman机器命令进行管理。Mac和Windows上的Podman还监听Docker API客户端,支持直接使用基于Docker的工具和从您选择的语言进行编程访问。

容器仓库

配置镜像仓库
打开配置文件 /var/home/core/.config/containers/registries.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
unqualified-search-registries = ["docker.io", "quay.io", "docker.m.daocloud.io"]

[[registry]]
prefix = "docker.io"
location = "registry-1.docker.io"

[[registry.mirror]]
location = "mirror.baidubce.com"

[[registry]]
prefix = "quay.io"
location = "quay.io"

[[registry.mirror]]
location = "quay-mirror.qiniu.com"

[[registry]]
prefix = "docker.m.daocloud.io"
location = "docker.m.daocloud.io"
## [[registry]]
## prefix = "example.com/foo"
## insecure = false
## blocked = false
## location = "internal-registry-for-example.com/bar"

底层原理

Podman和Docker都可以直接在Linux上运行,但是如果是在Windows或者MacOS上,需要创建一个linux的虚拟机,让Docker和Podman在虚拟机中运行。Docker的方式是通过Docker Desktop来创建Linux虚拟机,而Podman则是需要手动podman machine init来创建Linux虚拟机。

Podman和Docker区别

alt text