无法在Mac的启动台找到新安装的软件图标

问题

最近在Mac上装了新软件,在启动台中没有像往常一样有新的图标出现。但是却可以在应用程序中找到新的软件

喷气式水母 老哥的CSDN 上找到了解决的方案,感谢这位老哥提供的解决办法

解决

简单来说一句话

1
2
mv ~/L*/Application\ Support/Dock/*.db ~/Desktop;
killall Dock;

分析

个人理解是把管理界面的相关数据移动到桌边,重启Dock以后因为数据缺失会重新生成数据

所以桌面会多出一个 desktoppicture.db 的文件,我打算保留一阵子,没什么问题再删除

当然也可以把文件移动到别的地方

后续

如果发现出现问题把desktoppicture.db 替换回 ~/L*/Application\ Support/Dock/*.db 目录就可以了(应该。。可以吧 QAQ)

Windows上的Brew:Chocolatey 包管理工具

上官网链接:Chocolatey.org

检查PowerShell

PowerShell官方文档&安装

chocolatey主要依赖与 PowerShell ,Windows10 如果开启自动升级的话会一直保持最新版本,最早的版本也是5.0,所以并不需要担心

查看本机PowerShell版本

1
$PSVersionTable

PSVersion 的值就是当前的版本号

使用管理员权限打开PowerShell

1
Start-Process powershell -Varb runAs

Windows8.1 以上版本可以在开始菜单右键中找到使用管理员打开PowerShell的选项

Windows7 升级 PowerShell

PowerShell升级选项

我个人的Windows7 的 PowerShell 是2.0的版本,升级过程也就在此记录一下,方便大家

安装Chocolatey

CMD命令行

1
2
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command 
"iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

PowerShell

资产负债入门

资产负债入门

针对研发、实施的简单入门

什么是资产、负债?

能够带来利息的,即为资产

需要付利息的,即为负债

什么是风险?

不确定即风险

什么是科目?

记账的分类手段

流动性风险

关注未来现金流的流入、流出

例子:

现金流发生日期 科目 流入/流出 现金流
2019/7/30 收入->工资 流入 5000
2019/7/20 支出->房贷 流出 8000
2019/8/30 收入->工资 流入 5000
2019/8/20 支出->房贷 流出 8000

当前日期为2019年7月1日

导出的报表

时间段 1月之内 1-2月
时间 2019-07-01到2019-07-31 2019-08-01到2019-08-31
收入->工资 5000 5000
支出->房贷 -8000 -8000
缺口 -3000 -3000
累计缺口 -3000 -6000

利率风险

关注现金流的折现、重定价

市值

  • 为什么需要市值?

    统一的度量衡

    image-20210302120530261

    image-20210302120536316

重定价

假定目前手上有一笔100万的定期存款,下个月到期,现在的收益率为10%。目前的收益率非常满意,但到期后是否还能找到如此划算的投资渠道呢?

不一定。或许有,或许没有。未知即为风险。这就是重定价风险。

现金流折现法

通用的公式:未来现金流/(1+利率)的剩余期限(年)次方

image-20210302123000612

市值是利率风险的载体,就像股价是上市公司经营好坏的载体。

如果公司经营变坏,股价下降。同理,利率(例如,余额宝收益率)上升,市值会下降。

如果利率上升5%,A银行市值下降10%,B银行市值下降5%,那么我们说A银行的利率风险较高。

动态模拟

image-20210302133859998

当蓝色部分是我们假设(非真实)的情况,我们分别对真实情况与假设情况进行模拟后对比,这个就叫情景模拟

image-20210302133906690

这时我们就要考虑买车时候符合我们的经济预期,当我们为车辆进行贷款时,我们就要考虑贷多少钱(量),贷款利率(价),贷多久(期限)是多少

SVN:代码版本控制系统

2. SVN介绍

2.1 简介

SVN全称Subversion,是一个开放源代码的版本控制系统,Subversion在2000年由CollabNet Inc开发,现在发展为Apache软件基金会的一个项目,同样是一个丰富的开发者和用户社区的一部分。

SVN是一个开放源代码的版本控制系统,管理着随时间改变的数据。这些数据放置在一个中央资料档案库(repository)中。这个档案库很像一个普通的文件服务器,不过他会记住每一次文件的变动。这样你就可以把档案恢复到旧的版本,或者浏览文件的变动历史。说的简单一点,SVN就是用于多个人共同开发同一个项目,共用资源的目的。

2.2 主要作用

  1. 目录版本控制

    Subversion实现了一个“虚拟”的版本控管文件系统,能够依时间跟踪整个目录的变动。目录和文件能够进行版本控制。

  2. 真实的版本历史

    Subversion中,可以增加(add),删除(delect),复制(copy),重命名(rename),无论是文件还是目录。所有的新加的文件都从一个新的、干净的版本开始。

  3. 自动提交

    一个提交动作,不是全部更新到了档案库中,就是完全不更新。这允许开发人员以逻辑区间建立并提交变动,以防止当部分提交成功是出现的问题。

2.3 基本概念

  • Repository():

头寸管理

基础概念介绍

是什么 为什么 原则 目标

头寸管理的概念及内容

资金头寸

资金头寸是指银行在一定时点或时期实际可用的资金款项,即有清偿力的货币性资产

资金头寸管理的作用

指对本外币资金的统一调度和管理,以实现银行资金的合理流动与配置,确保资金安全支付,有效控制流动性的风险,提高资金运用的总体效益。

头寸的类型

基础头寸

基础头寸=在央行的清算存款(备付金)+库存现金

  • 随时可用资金

  • 最终支付手段

可用头寸

可用头寸=基础头寸+到期同业往来+存放他行清算资金+系统内往来资金

  • 潜在的资金
  • 数量上与基础头寸不同,可能大于、小于基础头寸

头寸管理现状分析

未构建头寸管理系统

  • 头寸管理起步晚
  • 头寸管理模式粗旷
  • 没有头寸管理考核办法
  • 对头寸有一定的想法

已构建头寸管理系统

  • 头寸管理已经有一定经验
  • 有相对规范的头寸管理模式
  • 有头寸管理考核办法
  • 对头寸管理有明确的想法

现状分析

  • 手工管理,效率,工作量
  • 部门、机构之间沟通不规范
  • 无法实时监测全行交易状况、存在资金浪费
  • 缺少事后分析的依据

头寸管理的原则

统一调度

总行负责全行资金的统一调度,各行部应服从总行资金统一管理、协调

头寸集中

各行部统一将资金全部集中到总行,总行资金头寸应主要集中在人民银行账户,防止头寸分散

分级管理

建立总分联系资金头寸管理体系。

总行负责全行资金头寸管理,并对各行头寸进行监控、调拨;各行部负责本部门、本行资金头寸管理

分工负责

总行计财与总行部门及各分支机构应各负其责,切实履行管理责任,既要互相配合协作,又要相互监督,防范资金风险

头寸管理目标

实现电子化流程管理

目前银行的头寸管理工作基本是手工管理的方式,通过资金头寸管理系统,能够实现资金头寸的流程化管理,支持全行头寸预报、 头寸核销、头寸监测、头寸考核的信息化管理模式

实现日间实时监控

资金头寸管理系统提供资金头寸实时监测功能,可以切实加强银行日间资金头寸管理,方便总行能更加科学地预测资金流动、合理调度资金头寸

实现事后分析

为行方事后分析提供数据支持,同时,提供头寸预报误差的考核方案,协助总行头寸管理员做好头寸管理工作

资金头寸管理

头寸预报 头寸核销 头寸监测 头寸考核

头寸管理流程图

基础设置

  • 系统管理
  • 参数管理
  • 工作流管理
  • 客户维护
  • 头寸管理

头寸管理

头寸预报

是指分支机构及总行部室预报(提前一天或当天)当天及未来的资金计划,方便总行头寸管理员统一匡算全行头寸,实时掌握各部门及分支机构的头寸缺口情况,并做出资金规划。

头寸预报方式

  • 大额手工预报:对金额在规定阀值以上的走来款进行手工预报,包括明细预报和总额预报;
  • 到期数据预报:是对系统自动获取的明确有到期日的存量业务的选择性预报。

头寸预报类型

  • 大额逐笔预报:主要用于分支机构对一般存贷款业务及票据业务的预报;
  • 总额预报:主要用于金融市场部、国际业务部等总行部室对同业业务、债券投资、票据类等业务的走来款进行总额预报。

头寸核销

是指将头寸预报信息与实际交易信息进行汇总匹配,满足自动核销条件的将由系统自动核销,不满足自动核销条件的等待手工核销。

  • 自动核销

    核销规则:机构名称+客户号+收付方向+收付日期;

    容错比:80%-120%;

    核销金额:核销金额起点值

  • 手工核销

    核销规则:收付方向为唯一识别,根据实际情况进行勾选核销

    核销结果:手工核销且被总行头寸管理员豁免的数据不纳入误报次数考核

头寸监测

资金头寸管理的核心是保证全行资金安全支付。

  • 监测账户

    • 人行超额备付金账户余额
    • 存放同业活期账户余额
  • 头寸预警

    • 账户余额超限
    • 大额实际流水预警
  • 其他要素

    • 监测频率:一般为15分钟,支持手动刷新。
    • 预警:预警信息一般支持对预警金额、预警时间参数化设置,并对接行内的短信平台。

头寸考核

是指在日终时将头寸考核结果中未核销的部分进行准确率及误报次数考核,并根据全部预报与实际对比分析,考核预报分支机构预报的时间准确率

  • 准确率考核

    计算公式:MAX(1-|预报数据-实际数据|/预报数据*100%,0)

  • 误报次数考核

    基于所有未核销掉的预报及实际数据

  • 时间考核

    时间考核:对不同时间区间进行手工核销的客户(未得到豁免),分别设置扣分标准

  • 误报豁免

    对误报的数据如果能明确说明理由,可以进行误报豁免审批,申请通过后,该笔数据不纳入头寸考核

配置参数介绍

预报参数

  • 预报数据时间、起点值
  • 客户维护
  • 存量数据统计起点值

大额实际交易流水参数

  • 数据起点值

核销参数

  • 核销容错比例

检测账户参数

  • 法定准备金

预警参数

  • 大额突发交易数据预警
  • 备付金账户余额
  • 时间区间

其他参数

  • 工作流管理

数据介绍

日终存量数据

日终存量数据是资金头寸系统的重要支撑,主要有4大类

  • 到期数据预测
    • 对应功能:头寸预报中的大额存量业务到期查询功能
    • 数据范围:有到期日的数据
  • 公共参数
    • 数据范围:机构、科目、币种、行名行号
  • 客户信息
    • 对应功能:本币大额预报
    • 数据范围:客户名称、客户号、账号
  • 总账数据
    • 作用:用于总分对账

实际交易数据

头寸监测是头寸管理系统的重要功能之一,这一功能的实现需要实时数据的支撑。数据大致分为以下几方面

备付金账户

  • 对应功能:实时准备金账户查询
  • 数据来源:二代支付系统/核心系统
  • 取数频率:一般是15分钟
  • 数据处理:人行的账户一般需要通过计算获取。实时超备=实时准备金账户余额-法定存款准备金余额

实际交易数据

  • 对应功能:大额实际交易明细
  • 取数要求:一般有金额起点值要求。需要分析数据量。
  • 数据来源:大额、小额、网银、同城、DVP等
  • 取数频率:15分钟

大额交易预警

  • 对应功能:大额预警
  • 数据来源:实时交易数据
  • 取数频率:依据实时数据取数频率

Java注解与反射

Java注解与反射 (Java.Annotation)

注解入门

Annotation是从JDK5.0开始引入的技术

Annotation的作用

  • 不是程序本身,可以对程序作出解释(这一点和注释(comment)没什么区别)
  • 可以被其他程序(比如编辑器等)读取

Annotation的格式

  • 注解是以“@注释名”在代码中存在的,还可以添加一些参数值

    @SuppressWarnings(value=”unchecked”)

Annotation在哪里使用

  • 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问

内置注解

@Override

定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明

@Deprecated

定义在java.lang.Deprecated中,此注释可以用于修辞方法,属性、类,表示不鼓励程序员使用这样的元素,通常是因为他们很危险或者存在更好的选择

1
2
3
4
5
6
7
8
9
public class Demo{
@Deprecated
public static void test(){
System.out.println("Deprecated方法被执行");
}
public static void main(String[] args) {
test();
}
}

方法依然可以执行,但是在IDE中方法名上会有删除线 test();

@SuppressWarnings

定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息

与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数已经定义好了,我们选择性使用就好

  • @SuppressWarnings(“all”)
  • @SuppressWarnings(“unchecked”)
  • @SuppressWarnings(value={“unchecked”,”depercation”})

五笔输入法学习

G11 - 王旁青头戋(兼)五一

F12 - 土士二干十寸雨

D13 - 大犬三(羊)古石厂

S14 - 木丁西

A15 - 工戈草头右框七

如何拆字

字型 位置关系 字例
左右型 左右、左中右 和 树 提 部
上下型 上下、上中下 态 惹 从 蔽
杂合性 独体、全包围、半包围 身 国 同 函 这

汉字结构

  • 单字结构:构成汉字的字根只有一个

    上 五 日 小 八

  • 散 结构汉字:构成汉字的字根有两个,且两个字根有距离,不相交也不相连

    明 对 务 打 休

  • 连 结构汉字:由一个单笔画字根跟一个基本字根相连的汉字

    自 千

  • 交 结构汉字:由几个字根相互交叉构成

    内 果 夫 中 申 丰

拆分原则

  1. 书写顺序
  2. 取大优先
  3. 能连不交
  4. 能散不连

书写顺序

“书写顺序”是指在拆分汉字时,应该按照汉字的书写顺序(一般为“从左到右”、“从上到下”、“从内到外”),将其拆分为字根。

文字示例 书写顺序拆分
人 + 火
耳 + 又
宀 + 丁
西 + 女

取大优先

“取大优先”是指按照书写顺序拆分汉字时,拆分出来的字根应尽量“大”,拆分出来的字根的数量应尽量少

文字示例 取大优先拆分
六 +
贝 +

Maven:项目对象模型

Maven简介

Maven是干什么的

Maven是Apache组织中的一个颇为成功的开源项目,Maven主要服务于基于java平台的项目构建,依赖管理和项目信息管理

约定 > 配置

构建工具

Ant(XML)

  • 最早的构建工具,基于IDE,2000年左右就流行的Java构建工具

  • 因为是基于XML脚本编写的,脚本xml文件特别大。

  • 对工程构建过程中的过程控制特别好

Maven(Java)

项目对象模型,通过其描述信息来管理项目的构建,报告和文档的软件项目管理工具。

它填补了Ant的缺点,Maven 第一次支持了从网络上下载的功能,仍然采用xml作为配置文件格式

Maven专注依赖管理,使用Java编写

Gradle(groovy)

结合了Ant和Maven的优点,继承了Ant的灵活和Maven的生命周期管理

被Google作为Android御用的管理工具,他最大的区别是不用xml作为配置文件格式,采用了DSL格式,使脚本更加灵活简洁

三种工具的区别

Ant 比较老,一般是一些传统的软件公司或企业在使用。Maven使用Java编写,是当下大多数互联网公司使用的一个构造工具,中文文档相对齐全。Gradle使用groovy编写,目前比较新型的构建工具一些初创的互联网公司会使用,有很大的使用空间

Maven四大特性

依赖管理系统、多模块构建、一致的项目结构、一致的构建模型和插件机制

依赖管理系统(Jar项目的多模块)

Maven为Java引入了一个新的依赖管理系统jar包管理,jar升级后更改配置文件即可

在Java中,可以使用groupIdartifactIdversion组成的Coordination(坐标)唯一标示一个依赖。任何基于Maven的项目自身也必须定义这三个属性,生成的包可以是Jar包,也可以是war包或者jar包。

依赖引用方法

1
2
3
4
5
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>

Maven坐标为各种组件引入了秩序,任何一个组件都必须明确定义自己的坐标

  • groupId

    定义当前Maven项目隶属的实际项目-公司名称

    由于Maven中模块的概念,因此一个实际的项目,往往会被划分为很多模块。

    比如spring是一个实际项目,其对应的Maven模块会有很多,如spring-corespring-webmvc

  • artifactId

    该元素定义实际项目中胡一个Maven模块-项目名,推荐的做法是使用项目名称作为artifactId的前缀。

    比如spring-beanspring-webmvc

  • version

    该元素定义Maven项目当前所处的版本

多模块构建

(内容未填补)

一致性项目构建

Maven拥有一套自己的项目目录结构作为标准的Java项目结构,解决了使用不同IDE开发带来的目录不一致问题

Maven的设计理念就是 约定大于配置 (Conversion over configuration)

一致的构建模型和插件机制

  • 通过pom配置tomcat、jetty插件

安装Maven

Mac - brew安装 如何安装brew(内容未填补)

1
brew install maven

检查是否安装成功,查看maven版本信息

1
mvn -v

查看maven是否安装成功

为依赖仓库添加镜像

因为国内一些不可描述的原因,导致我们从Maven官方查找和拉取依赖的时候,可能会在网络上出现的一些问题。我们可以考虑通过修改Maven的一些配置,来访问国内的镜像仓库来加快我们的拉取速度

在查看maven信息时,我们可以看到通过brew安装的maven被安装到了下面这个目录中

/usr/local/Cellar/maven/3.6.3_1/libexec

我们进入目录查找,修改/conf/setting.xml文件中的内容

打开文件中,我们可以搜索mirrors找到下面这些信息

image-20201231210536577

根据阿里云Maven仓库的官网的相关信息,在mirrors标签中插入下面这段信息

1
2
3
4
5
6
7
<!-- 官方留下的那些注释不要动,在他们之后插入就可以 -->
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>

可以访问**阿里云Maven仓库**官网,查看具体的使用指南

更改依赖缓存目录

如果想将缓存的依赖存放到其他的位置,可以更改settings.xml文件中的<loaclRepository>中的地址

1
<loaclRepository>依赖存放目录</loaclRepository>

一般来讲大家的Mac都是一个盘,所以不用修改

创建Maven项目

手动创建

创建一个文件夹

  • 目录树
1
2
3
4
5
6
7
8
9
/ #根目录
|-src
| |-main #项目程序目录
| | |-java #项目java源码
| | |-resources #项目资源
| |-test #项目测试目录
| | |-java #项目的测试类
| | |-resources #测试使用的资源
|-pom.xml #Maven配置文件
  • 目录对应功能
目录 功能
/ 存放pom.xml及所有子目录
/src/main/java 项目的java源代码
/src/main/resources 项目的资源 property文件
/sec/test/java 项目的测试类 JUnit代码
/src/test/resources 测试使用的资源

创建pom.xml

POM(Project Object Model)

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
<?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>
<!--上面是Maven的声明文件,不用动-->

<!--公司名称-->
<groupId>com.xon</groupId>
<!--项目名称-->
<artifactId>mavenDemo</artifactId>
<!--版本号-->
<version>1.0.0</version>

<!--项目依赖-->
<dependencies>
<!--引用依赖-->
<dependency>
<!--定位项目组-->
<groupId>org.xon</groupId>
<!--定位项目名称-->
<artifactId>testOne</artifactId>
<!--定位项目版本-->
<version>1.0</version>
</dependency>
<!--引用另一个依赖-->
<dependency>
<groupId>org.xon</groupId>
<artifactId>testTwo</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
</project>

创建一个Java程序

/main/java目录下创建java项目,可以将此目录看做/src目录

简单建个HelloiWorld就好(内容未填补)

初始化Maven

启动终端,在项目的根目录运行代码

1
nvm compile

在运行成功以后会提示BUILD SUCCESS

在第一次初始化Maven时,会在网络上下载大量的资源,时间可能会比较长,请耐心等待,以后再运行就会好很多

在根目录也会多出一个target的文件夹,里面包含了相应java编译好的程序

指定项目main方法

1
mvn exec:java -Dexec.mainClass="com.xon.mavendemo.HelloWorld"

同样在终端项目根目录运行,同样耐性等待

查找依赖坐标

我们可以在Maven的官方仓库中找到所有的依赖和他们的坐标

例如我们查找mysql的JDBC驱动

在Maven仓库中查找Mysql驱动

我们点击我们想要的版本,在打开的页面就有相应的依赖坐标

查找MySQL的具体依赖坐标

Eclipse中集成Maven

Maven中引入服务器

在Maven中引入Jetty服务器

更改pom.xml中的build标签

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
<build>
<!-- 最终生成war包的名字 -->
<finalName>mavenDemo</finalName>
<!-- 插件 -->
<plugins>
<!-- 定位插件坐标,我这里找的是Jetty -->
<!-- https://mvnrepository.com/artifact/org.mortbay.jetty/jetty -->
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
<!-- 配置Jetty服务 -->
<configuration>
<!-- 设置java项目改动,服务自动刷新的时间间隔 -->
<scanIntervalSeconds>10</scanIntervalSeconds>
<!-- 设置项目的发布路径 -->
<contextPath>/demo</contextPath>
<connectors>
<!-- 定义服务端口号,不写默认8080 -->
<connector implementation="">
<port>8081</port>
</connector>
</connectors>
</configuration>
</plugins>
</build>

在Maven中引入Tomcat服务器

1
2
3
4
5
6
7
8
9
10
11
12
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8081</port>
<path>/demo</path>
<uriEncoding>UTF-8</uriEncoding>
<finalName>mavenDemo</finalName>
<server>tomcat7</server>
</configuration>
</plugin>

(内容未填补)- 因为Tomcat官方在7.0以后就停止了插件的支持,所以我实际实验以后才能给出详细的方法

Maven仓库的基本概念

Maven仓库就是存储Maven插件与jar包的文件位置,分为远程仓库与本地仓库

在Maven根据坐标查找构件的时候,首先在本地仓库中进行查找,如果没找到才会在远程仓库中查找,如果都没有找到,Maven就会报错

一般来说Maven项目目录下没有存放jar包的位置,使用的jar包都是通过配置文件从本地仓库中拉取的

远程仓库三种类型

中央仓库

是Maven默认的远程下载位置

私服

个人或公司搭建的私有仓库。一般用于节省公网带宽和时间,在局域网中搭建的私有仓库,用于代理所有外部的远程仓库

同时可以部署一些公司内部项目供其他项目使用

其他公共仓库

第三方的公共仓库,镜像仓库、社区仓库等非官方仓库

Maven环境下的多模块项目搭建

使用Maven环境下的多模块项目构建的特性完成Maven环境下多个模块的项目的管理与构建

我们用一个普通的JavaWeb项目来进行举例

我们知道一个JavaWeb项目分为Dao、Service与Web 三个层

我们将每一层拆分成一个单独的子模块,最终合并成一个项目来了解多模块的构建过程

创建根项目

根项目只用来整合子模块,所以内部不需要任何代码,只需要有pom.xml文件即可

为了规范Maven结构,我们新建一个原型,在里面写上我们的组名、项目名和版本号

创建新的原型

iShot2021-01-02 23.46.22

我们来选择项目名和文件存储位置

iShot2021-01-02 23.48.19

选择使用的Maven的版本和位置

我选择的是IDEA中内置的Maven,并且更改了aliyun的镜像,当然你也可以选择在下拉菜单中选择IDEA自动查找到的本地的Maven,或者在菜单中手动查找你下载的Maven目录

用户设置文件和本地存储库会自动根据你选择的Maven版本来改变

iShot2021-01-02 23.50.31

创建完成以后pom.xml中会自动生成我们的项目名和版本信息

image-20210103121908373

创建子模块

根项目创建完成以后,我们来创建子模块

iShot2021-01-02 23.53.46

我用dao包来模拟子模块,所以我选用quickstart原型来搭建我的java项目

如果是web模块,我们就选用web_app原型模版

iShot2021-01-03 13.51.40

iShot2021-01-02 23.58.42

iShot2021-01-02 23.59.19

创建完成以后,我们可以看到在父模块与子项目的pom.xml中都相互的引入的对应的信息

iShot2021-01-03 00.03.12

因为我们使用了原型模版,所以下方会自动编译,等待编译完成,我们可以看到项目已经完善了

iShot2021-01-03 13.59.49

我们把其他的子模块创建完成

image-20210103141325759

Maven项目打包

项目开发的三种环境

  • 开发环境

  • 测试环境

  • 生产环境

为环境建立相应目录

/src/resources目录中新建用于存储各种配置的文件夹

分别新建文件夹,并新建db.properties

  • /src/resouces/dev/db.properties(开发环境)
1
2
username=dev
password=dev1234
  • /src/resouces/test/db.properties(测试环境)
1
2
username=test
password=test1234
  • /src/resouces/product/db.properties(生产环境)
1
2
username=product
password=product1234

为Maven引用打包配置

在pom.xml中新建<profiles>标签中,没有

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
<!-- 开发环境的打包配置 -->
<profiles>
<profile>
<id>dev</id>
<properties>
<env>dev</env>
</properties>
<!-- 指定为默认环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
<!-- 测试环境的打包配置 -->
<profiles>
<profile>
<id>test</id>
<properties>
<env>test</env>
</properties>
</profile>
</profiles>
<!-- 生产环境的打包配置 -->
<profiles>
<profile>
<id>product</id>
<properties>
<env>product</env>
</properties>
</profile>
</profiles>

为环境配置目录建立引用

<build>标签中设置如何读取配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<resources>
<resource>
<directory>src/main/resources/${env}</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.tld</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>

$env对应打包时指定的 -P属性

执行打包指令

1
clean compile package -Dmaven.test.skip=true

clean : 清除之前的编译结果

compile : 编译

package : 打包

-Dmaven.test.skip=true : 跳过单元测试

1
clean compile package -Ptest -Dmaven.test.skip=true

-Pxxx : 指定配置文件,不指定为默认的环境(通过打包环境的<activation>定义默认环境)

xxx : 与读取配置中的$env对应

因为执行了clean指令,所以会覆盖掉以前的打包文件

完成打包

执行命令以后,会在/target中生成.war的包,用解压软件解压以后,可以在/WEB-INF/classes目录中看到db.properties中为我们指定的环境的db.properties

定义依赖范围

依赖冲突

Vue :前端整合框架

什么是Vue?

Vue.js是一套构建用户界面的框架 ,它不仅易于上手,还可以与其他的第三方库整合(Swiper)

Vue两大核心

  • 数据驱动界面改变

  • 组件化

Vue过渡动画

添加动画操作步骤

  • 将需要执行的动画元素放到transition组件中

    • 当transition组件中的元素显示时会自动查找 .v-enter / .v-enter-active / v-enter-to 类名
    • 当transit ion组件中的元素隐藏时会自动查找.v-leave / .v-leave-active / v-leave-to 类名
  • 我们只需要在.v-enterv-leave-to中指定动画开始的状态

    .v-enter-active .v-leave-active中指定动画执行的状态

    即可完成过渡动画

d

Vue组件&组件化

  • 什么是组件

在前端开发中,组件就是把一个很大的界面拆分成为多个小界面,每一个小界面就是一个组件

  • 什么是组件化

将大界面拆分成小界面就是组件化

  • 组件化的好处
    • 可以简化Vue实例代码
    • 可以提高复用性

Vue 全局组件

在任意一个Vue实例控制的区域中都可以使用

创建组件构造器

1
2
3
4
5
let Profile = Vue.extend({
template:'
<!--html代码-->
'
});

注册已经创建好的组件

1
Vue.componect(id,[defintion])

id : 给注册的组件起一个名字

defintion : 传入已经创建好的组件构造器

注意点:在创建组件指定组件的模版的时候,模版只能有一个根玉元素

使用注册好的组件

1
<id></id>

组件的简写方法

内部直接调用

1
2
3
4
5
6
<script>
// 直接将模版写到component内部
Vue.component(id,{
<!--html代码-->
})
</script>

自动调用 Vue.extend() 方法

外部调用

1
2
3
4
5
6
7
8
9
10
<script>
// 将模版包含到变量中
let obj = {
template:'
<!--html代码-->
'
}
// 将包含模版的变量绑定到组件
Vue.component(id,obj)
</script>

type方法

1
2
3
4
5
6
7
8
9
<script id="msg" type="text/html">
<!-- html代码 -->
</script>
<script>
// 将模版绑定到组件
Vue.componment(id,{
template:"#msg"
});
</script>

template封装方法(常用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 创建组件模版 -->
<template id="msg">
<!-- 同时因为template只能传递一个标签,
所以应该用一个div将所有指令包裹一下-->
<div>
<!-- html代码 -->
</div>
</template>
<script>
// 将模版绑定到组件
Vue.componment(id,{
template:"#msg"
});
</script>

在单文件Vue开发中,template应该定义在实例的外面

在Vue-cli中,有template应该在对应的.vue的文件中

Vue 局部组件

只能在自定义的那个Vue实例控制的区域中才可以使用

如何自定义一个局部组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
let app = new Vue({
el:"#app",
data:{},
methods:{},
// 在Vue实例中新增components:{}
components:{
"msg":{
// 将以创建的模版与"msg"进行绑定
template:"#msg"
}
}
})
</script>

创建组件模版的方式在定义Vue全局变量中有所讲解跳转

组件中的data与methods

data的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template id="add">
<div>
{{msg}}
</div>
</template>
<script>
// 在注册自定义组件时
// 在其中书写自定义组件中出现的data内容
Vue.component("addFn",{
template:"#add",
data:function(){
return {
msg:"data in template!"
}
}
})
</script>

在Vue的官方文档 - 组件基础中提到 data 必须是一个函数,所以定义不能使用原先实例中的定义方法

在自定义函数中使用data必须赋值一个函数,然后通过函数的返回值来定义有哪些数据

为什么data需要函数来返回

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
<div id="app">
<!-- 3.创建三个组件 -->
<showAdd></showAdd>
<showAdd></showAdd>
<showAdd></showAdd>
</div>
<!-- 1.创建组件模版 -->
<template id="add">
<div>
<button @click="addFn">加一</button>
<p>{{num}}</p>
</div>
</template>
<script>
// 2.注册组件
Vue.component("showAdd",{
template:"#add",
data:function(){
return {
num:0
}
},
methods:{
addFn(){
this.num++;
}
}
})
</script>

为什么data需要函数来返回的运行结果

在上面的的结果中可以看出,同时创建的3个组件的data是相对独立的,并没有因为一个组件的数值发上改变而影响到其他组件中的数值结果

因为每创建一个组件,就会调用一次data方法。所以每个组件都拿到了自己的data方法,然后在通过data方法的返回值拿到自己的数值

当然,不使用方法返回的方式的话,就是注册的多个组件公用一个data,会造成数据的混乱

methods的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template id="add">
<div>
<button @click="addFn">按钮</button>
</div>
</template>
<script>
// 在注册自定义组件时
// 在其中书写自定义组件中出现的methods内容
Vue.component("addFn",{
template:"#add",
methods:{
addFn(){
// 方法
}
}
})
</script>

Vue组件切换 v-if

1
2
3
4
<div id="app">
<add v-if="showAdd"></add>
<sub v-else></sub>
</div>

在创建组件时添加v-if-else方法可以显示或隐藏组件

组件注册与绑定请参考全局组件的创建 跳转

动态组件 component

1
<component v-bind:is="'add'"></component>

直接写死为add

当然也可以定义成动态的

动态写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="app">
<button @click="toggle">切换</button>
<component v-bind:is="toggleName"></component>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
toggleName:"add"
},
methods:{
toggle(){
this.toggleName = this.toggleName === "add"?"sub":"add";
}
}
})
</script>

保留状态 keep-live

当你在其中一个组件模版中添加inputcheckbox再进行切换时,你会发现在切换后,原先组件的属性并不会被保留。因为当组件被切换就会把组件进行销毁

这时我们可以在建立组件的时候使用<keep-alive>组件包围起来,状态就可以被保留

1
2
3
<keep-live>
<component v-bind:is="toggleName">
</keep-live>

动画效果

1
2
3
<transition mode="in-out">
<component v-bind:is="toggleName">
</transition>

同时可以使用in-outout-in指定过渡样式

父子组件

  • 什么是父子组件

    在一个组件中又定义了其他组件就是父子组件

    其实局部定义组件就是最简单的父子组件,因为我们说过可以把Vue实例看作把Vue实例看作是一个大组件

    我们在Vue实例中定义了局部组件,就相当于在大组件里面定义了小组件,所以局部组件就是最简单的父子组件

  • 如何定义其他的父子组件

    自定义组件中可以使用data,可以使用methods,当然组定义组件组件中也可以使用components

VueX

VueX是Vue配套的公共数据管理工具,我们可以将共享的数据保存到Vuex中,方便整个程序中的任何组件都可以获取和修改Vuex中保存的公共数据

创建Vuex对象

1
2
3
4
5
6
7
8
<script>
const store = new Vuex.Store({
// state功能与组件中的data,用来存放共享数据
state: {
count: 0
}
})
</script>

在组件中使用Vuex对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
// 父组件
Vue.component('topTemplate',{
template: '#topTemplate',
// 在顶级组件中导入Vuex
store: store,
// 一级子组件
components:{
'secTemplate': {
template: '#secTemplate',
// 二级子组件
components: {
'thiTemplate': {
template: '#thiTemplate'
}
}
}
}
})
</script>

在顶级组件中使用Vuex对象,所以子类都能继承Vuex对象

输出共享数据

1
2
3
<div>
{{this.$store.state.count}}
</div>
  • 效果

    Vuex is easy!

修改共享数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
// 一级子组件
components:{
'secTemplate': {
template: '#secTemplate',
methods: {
add(){
this.$store.state.count = this.$store.state.count + 1;
},
sub(){
this.$store.state.count = this.$store.state.count + 1;
}
}
}
}
</script>

在Vuex中不推荐直接修改共享数据

如果多个组件都修改了共享的数据,那么后期数据发生了错误,调试错误需要把每一个修改了数据的组件都需要检查一遍

使用方法修改共享数据

创建VueX对象的修改方法 mutations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
const store = new Vuex.Store({
// state功能与组件中的data,用来存放共享数据
state: {
count: 0
},
mutations:{
addCount(state){
state.count= state.count + 1
},
subCount(state){
state.count= state.count - 1
}
}
})
</script>

在执行mutations中定义的方法的时候,系统会自动给方法传递一个state属性

state中就保存了共享的数据

调用VueX对象的修改方法 commit

1
2
3
4
5
6
7
8
9
10
<script>
methods:{
add(){
this.$store.commit("addCount")
}
sub(){
this.$store.commit("subCount")
}
}
</script>

VueX的getter属性

getter方法类似于 Vue实例中的computed属性

定义Vuex的Getter方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
const store = new Vuex.Store({
// state功能与组件中的data,用来存放共享数据
state: {
msg: 'Vuex'
},
getter:{
formatMsg(state){
console.log("getter方法被执行了") // ==>只会输出一次
return state.msg + ' is very easy!'
}
}
})
</script>

调用Vuex的Getter方法

1
2
3
<div>
{{this.$store.getters.formatMsg}}
</div>

Vue Router

Vue Router和v-if / v-show 一样,是用来切换组件显示的

与v-if/v-show的不同

v-if / v-show 是用标记来切换(true/false

Vue Router哈希来切换(#/xxx

v-if / v-show 相比,Vue Router不仅能切换组件的显示,还能再切换的时候传递参数

使用步骤

定义组件

1
2
3
4
5
6
7
8
<script>
const one = {
template:"#one"
}
const two = {
template:"#two"
}
</script>

定义切换规则

1
2
3
4
5
6
<script>
const routes = [
{path:'/one', component: one },
{path:'/two', component: two }
]
</script>

创建路由对象

1
2
3
4
5
<script>
const router = new VueRouter({
routes: routes
});
</script>

将实例绑定到Vue中

1
2
3
4
5
6
7
8
<script>
let vue = new Vue({
el:'#app',
router: router,
data:{
}
})
</script>

切换到路由界面

1
2
3
4
<div id="app">
<a href="#/one"></a>
<a href="#/two"></a>
</div>

路由显示的位置

1
2
3
4
5
6
<div id="app">
<a href="#/one">切换到one页面</a>
<a href="#/two">切换到two界面</a>
<!-- 定义所指定的路由所指向的组件的显示位置 -->
<route-view></route-view>
</div>

其他的操作

除了这些路由的相关操作以外,为了让程序能够正常运行,我们还应该定义 one 和 two 两个组件

定义相应的组件

1
2
3
4
5
6
<template id="one">
<div>我是one页面</div>
</template>
<template id="two">
<div>我是one页面</div>
</template>

想了解template的用法 跳转

这时我们点击对应的 <a> 标签,就应该可以看到页面的变化了

router-link标签

1
2
3
4
5
6
<div id="app">
<router-link to="/one">切换到one界面</router-link>
<router-link to="/two">切换到two界面</router-link>
<!-- 定义所指定的路由所指向的组件的显示位置 -->
<route-view></route-view>
</div>

通过 <router-link>设定了urlHash值的话,就不用写#

to : 定义Hash

tag : 定义标签名,默认为<a>,在Vue3中已经被移除,使用了v-slot代替

linkActiveClass属性

1
2
3
4
5
6
7
8
9
10
11
<style>
.activeing{

}
</style>
<script>
const router = new VueRouter({
routes: routes,
linkActiveClass: 'activeing'
});
</script>

当路由为被激活状态时,会写入相应的class标签

定义在创建路由的步骤

重定向路由

当我们不带任何路由指向访问网站时,我们可以通过重定向的方式,强制加载相应的组件

1
2
3
4
5
6
7
<script>
const routes = [
{path:'/', redirect:'/one'}
{path:'/one', component: one },
{path:'/two', component: two }
]
</script>

路由传递参数

只要将Vue Router挂载到了Vue实例对象上,我们就可以通过vue.¥route拿到路由对象

只要能拿到路由对象,就可以通过路由对象拿到传递的参数

如何拿到路由参数

URL方式传递

在指定hash的时候,通过?key=value&key=value的方式传递

1
2
3
<div id="app">
<router-link to="/one?name=Xonline&website=xon.ink" tag="button">带参数的路由切换</router-link>
</div>

在组件的生命周期方法中,通过this.$route.query方式获取

1
2
3
4
5
6
7
8
<script>
const one = {
template: "#one",
created: function (){
console.log(this.$route.query)
}
}
</script>

在控制台中,我们可以看到我们接受到了一个对象,在对象的query中,我们可以看到我们发送的数据

在使用时,我们可以使用

1
2
this.$route.query.name // 输出 Xonline
this.$route.query.website // 输出 xon.ink

路由规则占位符传递

在指定路由规则的时候通过 /:key/:key的方式来指定占位符

1
2
3
4
5
6
7
8
9
<script>
// 在创建路由规则的时候
const routes = [
{
path: '/one/:name/:website',
component: one
}
]
</script>

在指定hash的时候通过/value/value的方式来传递值

1
2
3
<div id="app">
<router-link to="/one/Xonline/xon.ink" tag="button">带参数的路由切换</router-link>
</div>

书写参数时,要与占位符对应

在组件的生命周期方法中,通过this.$route.params方式来获取

1
2
3
4
5
6
7
8
<script>
const one = {
template: "#one",
created: function (){
console.log(this.$route.params)
}
}
</script>

URL传递的接收方式一样,来获取传递的数据

1
2
this.$route.params.name // 输出 Xonline
this.$route.params.website // 输出 xon.ink

嵌套路由(未完)

嵌套路由也称之为子路由,就是在被切换的组件中又切换其他子组件

watch属性

Watch属性是专门用于监听数据变化的,只要数据发生了变化,就会自动调用对应数据的回调方法

Watch属性如何监听路由变化

Watch属性不仅仅能够监听数据的变化,还能监听路由地址的变化

Vue-CLI 手脚架工具

  • Command Line Interface

    Vue-CLI是Vue官方提供的手脚架工具

    默认已经帮我们搭建好了一套利用webpack管理vue的项目结构

安装&使用 Vue-cli

事先需要安装node.js,更新npm

安装手脚架

1
npm install -g @vue/cli

检查是否安装成功

1
vue --version

通过手脚架创建项目

1
vue create project-name

Vue-cli目录

node_modules : 存放当前项目的依赖包

public :

src :

build :

config :

为什么没有webpack配置文件

当使用Vue-cli 3.x以后的版本 webpack的配置文件被隐藏起来的了

手动配置Vue项目

  • 选择手动配置Vue-cli

选择手动配置Vue-cli

  • 选择需要安装的插件&依赖

选择需要安装的插件&依赖

按上下方向键选择,空格选中,回车下一步

Babel :

TypeScript :

Progressive Web App (PWA) Support :

Router : 路由

Vuex : 共享数据

CSS Pre-processors : CSS预处理器

CSS预处理器选择

Linter / Formatter : 代码规范检查 / 格式化代码工具

代码规范检查模式选择

Unit Testing : 单元测试

E2E Testing :

MyBatis:热门的持久层框架

事先声明

本人根据 bilibili 视频博主楠哥教你学Java所发布的视频【极简入门】4小时学会MyBatis的课程内容进行学习及整理

本视频应该是我在B站找到的单独讲解MyBatis的所有视频中最精简,最快速的学习视频,非常适合于我一样,马上毕业了的大四小白🐶

在这里进行强烈推荐

本人为了便于学习,将其挂在了我的个人网站上,如对UP主的权益有所侵犯,请通过admin@xon.ink与我联系

MyBatis简介

MyBatis是 Apache 的一个开源项目 iBatis ,2010年这个项目由 Apache Software Foundation迁移到了 Google Code,并改名为 MyBatis,2013年11月迁移到了 Github

现在的MyBatis中依然有很多依然用iBatis命名的包名,没有改过来

MyBatis 是一个是一个实现了数据持久化的开源框架,简单理解就是对 JDBC 进行了封装

ORMapping:对象关系映射

ORMapping:对象关系映射 (Object Relationship Mapping)

对象指面向对象(Java)

关系指关系型数据库(MySQL或关系型数据库)

Java到MySQL的映射,开发者可以以面向对象的思想来管理数据库

MyBatis的优点

  • 与JDBC相比,减少了50%以上的代码量
  • MyBatis是最简单的持久化框架,小巧并且简单易学
  • MyBatis相当灵活,不会对应用程序或数据库现有的设计强加任何影响,SQL写在了XML中,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用
  • 提供XML标签,支持动态编写SQL语句
  • 提供映射标签,支持对象与数据库的ORM字段关系映射

MyBatis的缺点

  • SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此。对开发人员编写SQL语句的功底有一定的要求
  • SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库

MyBatis的核心接口和类

graph TD
SqlSessionFactoryBuilder -.build.-> SqlSessionFactory -.openSession.->SqlSession

MyBatis的开发方式

  • 使用原生接口
  • Mapper代理实现自定义接口

搭建MyBatis环境(IDEA)

创建简单的数据模型

因为是ORMapping

我们需要分别创建关系类型 (Relationship) ,以及对象 (Object) 类型的创建

并且两者的数据应该互相匹配在能在后期完成映射

创建Maven pom.xml

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
<configuration>
<dependencies>
<!-- 导入Mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<!-- 导入Mysql依赖(因为Mybatis基于JDBC) -->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<!-- 插入自定义规范依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<!-- Maven中无法读取main目录下的xml文件
所以在pom.xml文件中加入对应的<build>标签及内容 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</configuration>

创建数据表

1
2
3
4
5
6
create table t_account(
id int primary key auto_increment,
username varchar(11),
password varchar(11),
age int
)

创建对象

  1. 新建数据表对应的实体类Account
1
2
3
4
5
6
7
8
9
import lombok.Data;

@Data
public class Account {
private long id;
private String username;
private String password;
private int age;
}

创建MyBatis全局配置文件config.xml

文件名可以自定义

创建配置文件config.xml ,在项目src/main/resources目录中(Maven中)

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--XML头文件-->

<configuration>
<!-- 配置MyBatis运行环境 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC的事务管理 -->
<transactionManager type="JDBC"></transactionManager>

<!-- POOLED配置JDBC数据源链接池 -->
<dataSource type="POOLED">
<!-- 配置JDBC的四个步骤 -->
<!-- 1.配置JDBC驱动 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
<!-- 2.配置JDBC链接路径
当然可以指定字符集,在链接末尾加入
?useUnicode=true&amp;characterEncoding=UTF-8 -->
<property name="url" value="jdbc:mysql://localhost:3306/databaseName"></property>
<!-- 3.配置数据库的用户名 -->
<property name="username" value="root"></property>
<!-- 4.配置数据库的密码 -->
<property name="password" value="1234"></property>
</dataSource>
</environment>

<!-- 为了适应多个数据源的链接
environment标签必须包含在environments标签中
<environment id="development1">
<transactionManager type=""></transactionManager>
<dataSource type=""></dataSource>
</environment>
-->
</environments>
</configuration>
graph TD
subgraph config.xml
    mysql(MySQL)
    subgraph environments
      transactionManager -.配置JDBC事务.-> JDBC
      dataSource -.配置JDBC数据池.-> JDBC
      JDBC --> mysql
  end
  subgraph mappers
      mapper -.注册mapper文件.-> mapper.xml
  end
end

使用原生接口

Mybatis框架需要开发者自定义SQL语句,写在Mapper.xml文件中,在实际开发中,会为每个实体类创建对应的Mapper.xml,定义管理该对象数据的SQL

新建对应类的Mapper

新建放置mapper文件的包,里面统一放置Mapper的xml文件

在包中新建一个xml文件,命名为XXXXMapper.xml,名字应与类对应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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">
<!-- XML头文件 -->

<mapper namespace="com.xon.mapper.AccountMapper">
<!-- Mybatis的每种操作在Mapper文件中都有对应的标签-->

<!-- 表添加动作的标签 -->
<insert id=""></insert>
<!-- 表修改动作的标签 -->
<update id=""></update>
<!-- 表删除动作的标签 -->
<delete id=""></delete>
<!-- 表查询动作的标签 -->
<select id=""></select>
</mapper>
  • namespace 通常设置为文件所在包+文件名的形式

  • 具体例子

    1
    2
    3
    4
    5
    6
    <mapper namespace="com.xon.mapper.AccountMapper">
    <insert id="save" parameterType="com.xon.entity.Account">
    insert into t_account(username,password,age)
    values(#{username},#{password},#{age})
    </insert>
    </mapper>
    • id 是实际调用Mybatis方式时需要调用的参数
    • parameterType 是调用对应方法时参数的数据类型

在全局配置中注册Mapper

config.xml文件中添加相应标签注册AccountMapper.xml

1
2
3
4
5
6
<configuration>
<!-- 在底部继续添加 -->
<mappers>
<mapper resource="com/xon/mapper/AccountMapper.xml"></mapper>
</mappers>
</configuration>

因为注册文件的路径需要添加.xml文件的后缀。如果用符号.对文件目录进行分割的话,就无法区分后缀还是子目录

所以目录之间用 / 代替

调用原生接口执行添加操作

新建放置repository文件的包(未完成)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DemoByNative {
public static void main(String[] args) {
//加载MyBatis配置文件
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//指定Mapper的位置 路径为 namespace.id
String statement = "com.xon.mapper.AccoutMapper.save";
//创建数据对象
Account account = new Account(1L,"张三","123123",22);
//执行添加操作(Mapper路径,添加的数据)
sqlSession.insert(statement,account);
//提交事物
sqlSession.commit();
//关闭
sqlSession.close();
}
}

Mapper代理实现自定义接口

  • 自定义接口,定义相关业务方法
  • 编写与方法相对应的Mapper.xml
  • 在接口中声明对象 –> 在mapper.xml中添加方法8

自定义接口

创建包repository

创建接口 AccountRepository

1
2
3
4
5
6
7
8
9
10
11
12
public interface AccountRepository {
// 实现增加的方法
public int save(Account account);
// 实现修改的方法
public int update(Account account);
// 实现删除的方法,通过查找id的方式
public int deleteById(long id);
// 实现查询的方法
public List<Account> findAll();
// 实现查询的方法,通过查找id的方式
public Account findById(long id);
}

创建接口对应的Mapper.xml

定义接口方法对应的SQL语句

<statement> 标签可以根据SQL执行的业务选择 insertdeleteupdateselect

Mybatis 框架会根据规则自动创建接口实现类的代理对象

在repository中创建AccountRepository.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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">
<!-- XML头文件 -->

<mapper namespace="com.xon.repository.AccountRepository">
<insert id="save" parameterType="com.xon.entity.Account">
insert into t_account(username,password,age) values(#{username},#{password},#{age})
</insert>
<update id="update" parameterType="com.xon.entity.Account">
update t_account set username = #{username},password = #{password},age = #{age} where id = #{id}
</update>
<delete id="deleteById" parameterType="long">
delete from t_account where id = #{id}
</delete>
<select id="findAll" resultType="com.xon.entity.Account">
select * from t_account
</select>
<select id="findById" parameterType="long" resultType="com.xon.entity.Account">
select * from t_account where id = #{id}
</select>
</mapper>

规则

  • Mapper.xml 中 namespace.xml 为接口的全类名
  • Mapper.xml 中 statement 的 id 为接口中对应的方法名
  • Mapper.xml 中 statement 的 parameterType 和接口中对应的方法参数一致
  • Mapper.xml 中 statement 的 resultType 和接口中对应方法的返回值类型一致

小知识

insertdelete 返回执行语句的行数,肯定为int所以不用指定返回类型

delete中的parameterType也可以写全”java.lang.long”

查询语句不应该写<List> 应该写Account的范型

在全局配置文件中注册Mapper

1
2
3
4
<configuration>
<!-- 在底部继续添加 -->
<mappers resource="com/xon/repository/AccountRepository.xml"></mappers>
</configuration>

调用代理接口执行操作

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
public class DemoByProxy {
public static void main(String[] args) {
//加载MyBatis配置文件
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取实现接口的代理对象
AccountRepository accountRepository = sqlSession.getMapper(AccountRepository.class);
//添加对象
Account account = new Account(2L,"李四","123123",23)
accountRepository.save(account);
//增删改操作一定要提交事物
sqlSession.commit();
sql.close();

//查找所有
List<Account> list accountRespository = findAll();
for(Account account:list){
System.out.println(account);
sqlSession.close();
}

//通过Id查询
Account account = accountRespository.findById(3L);
System.out.println(account);
sql.close();

//修改对象
Account account = accountRespository.findById(3L);
account.setUsername("小明");
account.setPassword("000");
account.setAge(18);
int result = accountRespository.update(account);
System.out.println(result);
sqlSession.commit();
sqlSession.close();

//通过Id删除对象
int result = accountRespository.deleteById(3L);
System.out.println(result);
sqlSession.commit();
sqlSession.close();
}
}

Mapper.xml

statement 标签

  • select : 查询
  • update : 修改
  • delete : 删除
  • insert : 添加

parameterType 参数数据类型

  • 基本数据类型通过Id查询 Account

    1
    2
    3
    <select id="findById" parameterType="long" resultType="com.xon.entity.Account">
    select * from t_account where id = #{id}
    </select>
  • String类型,通过 name 查询 Account

    1
    2
    3
    <select id="findByName" parameterType="java.lang.String"resultType="com.southwind.entity.Account">
    select * from t_account where username = #{username}
    </select>

    想实现name查找,在别忘了在接口中定义方法

  • 包装类,通过id查询Account

    1
    2
    3
    <select id="findById2" parameterType="java.lang.Long" resultType="com.southwind.entity.Account">
    select * from t_account where id = #{id}
    </select>

    其实和id查询的区别就是把long 换成了对象

    好处就是可以返回null值了

  • 多个参数,通过nameage查询 Account

    1
    2
    3
    <select id="findByNameAndAge" resultType="com.southwind.entity.Account">
    select * from t_account where username = #{param1} and age = #{param2}
    </select>

    因为多个参数无法指定一种类型,所以不用写参数类型

    sql中通过下标的方式来指定参数,下面是指定下标的两种方式

    • param:下标从 1 开始,{param1}{param2}
    • arg : 下标从 0 开始,{arg0}{arg1}
  • JavaBean

    1
    2
    3
    <update id="update" parameterType="com.xon.entity.Account">
    update t_account set username = #{username},password = #{password},age = #{age} where id = #{id}
    </update>

resultType 结果类型

  • 基本数据类型,统计Account总数

    1
    2
    3
    <select id="count" resultType="int">
    select count(id) from t_account
    </select>
  • 包装类,统计 Account 总数

    1
    2
    3
    <select id="count" resultType="java.lang.Integer">
    select count(id) from t_account
    </select>
  • String 类型,通过 id 查询 Account 的 name

    1
    2
    3
    <select id="findNameById" resultType="java.lang.String">
    select username from t_account where id = #{id}
    </select>
  • Java Bean

    1
    2
    3
    <select id="findById" parameterType="long" resultType="com.xon.entity.Account">
    select * from t_account where id = #{id}
    </select>

级联查询

一对多关系

请我喝杯咖啡吧~

支付宝
微信