liquibase的changelog详解

转载自两位大佬的文章,原文链接:https://zhuanlan.zhihu.com/p/157714666https://blog.csdn.net/a112626290/article/details/104263790

二、changelog 详解

1.什么是changelog?

changelog 是 Liquibase 进行版本管理的核心文件。

  • 官方介绍

The root of all Liquibase changes is the changelog file. Liquibase uses a changelog to list all changes, in order, made to your database. Think of it as a ledger. It is a file that contains a record of all your database changes (changesets). Liquibase uses this changelog record to audit your database and execute any changes not yet applied to your database.

hangelog 是 Liquibase 版本控制的核心,Liquibase 通过有序的 changelog 罗列你对数据库的更改,你可以把它想象成为一个账本,包含你对数据库所有操作的文件。

Liquibase 使用这个变更日志来审计你的数据库,并执行任何还没有应用到目标数据库的变更操作

简而言之就是一个日志文件,可以理解成 MySql 的 binlog 重做日志,Hadoop 的 NameNode 日志,提供重现步骤

2. changelog 的格式

Liquibase 提供的 changelog 格式有5种:

  • SQL
  • XML
  • JSON
  • YAML
  • Other

其中建议使用的是 XML ,其次是 YAML,原因是可读性高。所以这里只讲XML和YAML

2.1.XML 格式

<?xml version="1.0" encoding="UTF-8"?>  <databaseChangeLog  xmlns="http://www.liquibase.org/xml/ns/dbchangelog"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsdhttp://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">  <preConditions>  <runningAs  username="liquibase"/>  </preConditions>  <changeSet  id="1"  author="nvoxland">  <createTable  tableName="person">  <column  name="id"  type="int"  autoIncrement="true">  <constraints  primaryKey="true"  nullable="false"/>  </column>  <column  name="firstname"  type="varchar(50)"/>  <column  name="lastname"  type="varchar(50)">  <constraints  nullable="false"/>  </column>  <column  name="state"  type="char(2)"/>  </createTable>  </changeSet>
</databaseChangeLog>

2.2 YAML 格式

使用 JSON 需要下载:snakeyaml-1.12.jar ,并加入到 classpath 中

databaseChangeLog:  -  changeSet:  id:  1  author:  nvoxland  changes:  -  createTable:  tableName:  person  columns:  -  column:  name:  id  type:  int  autoIncrement:  true  constraints:  primaryKey:  true  nullable:  false  -  column:  name:  firstname  type:  varchar(50)  -  column:  name:  lastname  type:  varchar(50)  constraints:  nullable:  false  -  column:  name:  state  type:  char(2)

3.changelog 嵌套元素

changelog 可用的嵌套元素共5类:

  • preConditions:执行 changelog 的前置条件;
  • property:用于设置属性的值;
  • changeSet:执行的变更集
  • include:引用其他包含要执行的 changeSet 文件;
  • context:changSet 上下文;

这些嵌套元素将在编写 changelog 时详细说明,接下来,让我们写一个简单的 changelog ,完成我们的数据库升级

4、实战

1、优化

首先,我们可以从二-5中看到update,执行过程中,如果每次命令都需要加这么一堆参数就显得很繁琐,没关系,Liquibase提供了优化的方案。

  • 我们可以通过内置的 liquibase.properties 文件,预定义我们的一些变量,如图:
# 版本控制主文件
driver:com.mysql.cj.jdbc.Driver
url:jdbc:mysql://localhost:3306/liquibase?useSSL=false
username:root
password:admin
# jdbc 驱动
classpath:./mysql-connector-java-8.0.11.jar
changeLogFile:./sql/my/text.xml

这样在 liquibase.properties 同级目录下,直接执行 liquibase update liquibase rollbackCount 2即可。

  • 就像这样
  • 以下所以的实战默认已有properties文件,配置好了所有信息,并在同级目录下执行

2、目标数据库状态

创建表 user ,字段 id,name,age添加初始化数据:(1,"张三",18),(2,"李四",19),(3,"王五",19)

3、使用命令

3.1.update
liquibase update
3.2.rollback
liquibase rollbackCount 2

4、编写changelog文件

空的changelog格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog  xmlns="http://www.liquibase.org/xml/ns/dbchangelog"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"  xmlns:pro="http://www.liquibase.org/xml/ns/pro"  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsdhttp://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsdhttp://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-3.8.xsd ">
</databaseChangeLog>

5、添加changeSet

5.1.原生SQL格式

样例如下,分布执行两步,两个 changeSet,第一建表,第二步插入数据

是更新时使用的, 是回滚时使用的

<changeSet id="create-user" author="jiaotd"><sql>CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;</sql><rollback><sql>drop database `user`;</sql></rollback><comment>创建user表</comment></changeSet><changeSet id="insert-user" author="jiaotd"><sql>insert into user values(1,"张三",18),(2,"李四",19),(3,"王五",19);</sql><rollback><sql>delete from user;</sql></rollback><comment>创建user表</comment></changeSet>

执行update操作,显示Liquibase: Update has been successful.即代表成功。

可以看到,数据库多了3张表:DATABASECHANGELOG,DATABASECHANGELOGLOCK,user

其中 user 是我们自己定义的表,而剩下两张表则是 Liquibase 本身所需要的表。

打开 user 表,看一下我们的数据是否正确。

剩余的两张 Liquibase 的表,DATABASECHANGELOGLOCK 是Liquibase 在处理并发操作时一个锁表,正常情况下不用关心,DATABASECHANGELOG 则是 Liquibase 对数据进行版本管理的核心,如图:

列描述在上一篇文章已经提到,这里就不再赘述,重点看DESCRIOTION,字段值是SQL,代表我们使用了 SQL 格式的 changeSet。

执行rollback命令后,就可以看到 user 表被删除,另外DATABASECHANGELOG处于清空状态。

5.2.SQLFile格式

首先我们先定义 update 与 rollback 执行的 SQL 文件

creat-user.sql

CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;insert into user values(1,"张三",18),(2,"李四",19),(3,"王五",19);

create-user-rollback.sql

drop table `user`;

然后,新建一个 test-sqlfile.xml 文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLogxmlns="http://www.liquibase.org/xml/ns/dbchangelog"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangeloghttp://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd"><changeSet id="init-user" author="jiaotd"><sqlFile path="create-user.sql" relativeToChangelogFile="true"/><rollback><sqlFile path="create-user-rollback.sql" relativeToChangelogFile="true"/></rollback><comment>初始化user表</comment></changeSet></databaseChangeLog>

最后,执行update操作,同样可以实现刚才的效果,DATABASECHANGELOG 如图所示:

这里注意看 DESCRIOTION,值是 sqlFile,代表我们使用了 SQLFile 格式的 changeSet 。

5.3.原生XML标签格式

创建一个新的 changelog 文件,命名为 test-xml.xml,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLogxmlns="http://www.liquibase.org/xml/ns/dbchangelog"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangeloghttp://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd"><changeSet id="create-user" author="jiaotd"><createTable tableName="user"><column name="id" type="int(11)" autoIncrement="1"/><column name="name" type="varchar(1255)"/><column name="age" type="int(11)"/></createTable><addPrimaryKey tableName="user" columnNames="id"/><rollback><dropTable tableName="user"/></rollback></changeSet><changeSet id="add-user" author="jiaotd"><insert tableName="user"><column name="id" value="1"/><column name="name" value="张三"/><column name="age" value="18"/></insert><insert tableName="user"><column name="id" value="2"/><column name="name" value="李四"/><column name="age" value="19"/></insert><insert tableName="user"><column name="id" value="3"/><column name="name" value="王五"/><column name="age" value="19"/></insert></changeSet></databaseChangeLog>

这里注意看DATABASECHANGELOG 的 DESCRIOTION,值是 类似于伪代码的内容,代表我们使用了原生xml 格式的 changeSet

5、标签详解

可以用include引入其他版本修改历史文件,如下图:

5.1.XML格式

tag Description
preConditions 执行sql变更文件的前置条件
property 设置的属性的值
changeSet 要执行的更改
include 包含要执行的更改集的附加文件
context 上下文将被附加到(使用AND)所有变更集
5.1.1.preConditions标签

可以应用于<databaseChangeLog>标签或者<changeSet>标签。

<?xml version="1.0" encoding="UTF-8"?><databaseChangeLogxmlns="http://www.liquibase.org/xml/ns/dbchangelog"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangeloghttp://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd"><preConditions><dbms type="oracle" /><runningAs username="SYSTEM" /></preConditions><changeSet id="1" author="bob"><preConditions onFail="WARN"><sqlCheck expectedResult="0">select count(*) from oldtable</sqlCheck></preConditions><comment>Comments should go after preCondition. If they are before then liquibase usually gives error.</comment><dropTable tableName="oldtable"/></changeSet>
</databaseChangeLog>

上述的示例,是只有在Oracle数据库以及用户是SYSTEM时才会执行。

preConditions前置条件分为正常和异常情况:
正常情况下,无论返回的值是不是预料的值(0),oldtable都会被删除,只是如果不是预料的值,这里会给出WARN;
异常情况下,也就是如果oldtable不存在,删除oldtable的命令将不会执行。

(1)处理失败和错误
Attribute Description
onFail 当preConditions是失败情形下如何处理
OnError 当preConditions是错误情形下如何处理
onSqlOutput 在updateSQL模式下要做什么
onFailMessage 输出的失败信息
onErrorMessage 输出的错误信息
OnFail/OnError值可能配置的值
Value Description
HALT 立即停止执行整个更改日志。 [默认]
CONTINUE 跳过* changeSet 。 下次更新时将再次尝试执行更改集。 继续 changelog *。
MARK_RAN 跳过更改集,但将其标记为已执行。继续更改日志。
WARN 输出警告并继续照常执行* changeSet * / * changelog *。
onSqlOutput可能配置的值
Value Description
TEST 在updateSQL模式下运行changeSet
FAIL 使preConditons在updateSQL模式下失败
IGNORE 忽略updateSQL模式中的preConditons(默认)。
(2)and/or/not逻辑

可以使用nestable <and><or><not>标记将条件逻辑应用于前置条件。如果没有指定条件标记,则默认为AND。

<preConditions onFail="WARN"><dbms type="oracle" /><runningAs username="SYSTEM" />
</preConditions>

这里就是默认值AND,也就是同时满足既是oracle数据库,并且用户必须是SYSTEM才会执行。

如果使数据更改可以在oracle和mysql中可以执行,需要用到or表达式:

<preConditions><or><dbms type="oracle" /><dbms type="mysql" /></or></preConditions>

复合条件,例如,是oracle数据库,并且用户必须是SYSTEM 或者 数据库是mysql,且用户需要为root时,可以这样写:

<preConditions><or><and><dbms type="oracle" /><runningAs username="SYSTEM" /></and><and><dbms type="mysql" /><runningAs username="root" /></and></or></preConditions>
(3)可用的preConditions
  • <dbms>:如果针对指定类型执行的数据库匹配,则可以传递。
<dbms type="mysql" />
1
  • <runningAs>:执行执行的用户,匹配才可以传递。
<runningAs username="root" />
1
  • <changeSetExecuted>:如果指定的changeSet被执行了才可以传递。
<changeSetExecuted id="1" author="YoungLu" changeLogFile="classpath:liquibase/changelog/2020-02-11-change.xml" />
1
  • <columnExists>:如果数据库中的指定列存在则传递
<columnExists schemaName="young_webchat" tableName="y_user" columnName="username" />
1
  • <tableExists>:如果数据库中的表存在,则传递
<tableExists schemaName="young_webchat" tableName="y_user" />
1
  • <viewExists>:如果数据库中的视图存在,则传递
<viewExists schemaName="young_webchat" viewName="y_user_view" />
1
  • <foreignKeyConstraintExists>:如果外键存在则传递
<foreignKeyConstraintExists schemaName="young_webchat" foreignKeyName="y_user_log_fk" />
1
  • <indexExists>:如果索引存在则传递
<indexExists schemaName="young_webchat" indexName="y_user_idx" />
1
  • <sequenceExists>:如果序列存在则传递
<sequenceExists schemaName="young_webchat" sequenceName="y_user_seq" />
1
  • <primaryKeyExists>:如果主键存在则传递
<primaryKeyExists schemaName="young_webchat" primaryKeyName="y_user_id" />
1
  • <sqlCheck>:执行SQL检查。SQL必须返回具有单个值的单个行。
<sqlCheck expectedResult="1">SELECT COUNT(1) FROM pg_tables WHERE TABLENAME = 'myRequiredTable'</sqlCheck>
1
  • <changeLogPropertyDefined>:检查给定的changelog参数是否存在。如果一个值也是给定的,如果这个值与给定的值不相同那么它只会失败。
<changeLogPropertyDefined property="myproperty"/>
<changeLogPropertyDefined property="myproperty" value="requiredvalue"/>
12
  • <customPrecondition>:可以通过创建实现liquibase.precondition的类来创建自定义前置条件。CustomPrecondition接口。自定义类的参数是通过基于子标记的反射设置的。参数作为字符串传递给自定义前置条件。
<customPrecondition className="com.example.CustomTableCheck"><param name="tableName" value="our_table"/><param name="count" value="42"/>
</customPrecondition>
5.1.2.Properties标签

为changelog定义一个参数。给定上下文 和/或 数据库的列表,该参数将仅在这些上下文 和/或 数据库中使用。

示例:

<databaseChangeLogxmlns="http://www.liquibase.org/xml/ns/dbchangelog"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsdhttp://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd"><property name="clob.type" value="clob" dbms="oracle"/><property name="clob.type" value="longtext" dbms="mysql"/><changeSet id="1" author="joe"><createTable tableName="${table.name}"><column name="id" type="int"/><column name="${column1.name}" type="${clob.type}"/><column name="${column2.name}" type="int"/></createTable></changeSet>
</databaseChangeLog>
  • 可用的配置项
Attribute Description
name 表的数据库名称
value 所需列的表的名称
context 上下文,逗号分隔
dbms 要用于该changeSet 的数据库的类型。关键字all和none也可用。
global 定义属性是全局的还是局限于databaseChangeLog。“true”或“false”。

示例:

<property name="simpleproperty" value="somevalue"/>
<property name="clob.type" value="clob" dbms="oracle,h2"/>
<property name="clob.type" value="longtext" dbms="mysql"/>
<property name="myproperty" value="yes" context="common,test"/>
<property name="localproperty" value="foo" global="false"/>
5.1.3.changeSet标签

将一个个数据库更改分开。

示例:

<?xml version="1.0" encoding="UTF-8"?><databaseChangeLogxmlns="http://www.liquibase.org/xml/ns/dbchangelog"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:pro="http://www.liquibase.org/xml/ns/pro"xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsdhttp://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-3.8.xsd"><changeSet id="1" author="bob"><comment>A sample change log</comment><createTable/></changeSet><changeSet id="2" author="bob" runAlways="true"><alterTable/></changeSet><changeSet id="3" author="alice" failOnError="false" dbms="oracle"><alterTable/></changeSet><changeSet id="4" author="alice" failOnError="false" dbms="!oracle"><alterTable/></changeSet></databaseChangeLog>

一般主要由“id” 、“author”、changelog文件路径名组成

(1)可用的属性值:
属性 描述
id 唯一识别,不一定是数字
author 作者
dbms 数据库类型
runAlways 在每次运行时执行changeset ,即使之前已经运行过
runOnChange 在第一次看到更改时执行更改,并且在每次changeset 时执行更改
context 控制是否执行changeset,这取决于运行时设置。任何字符串都可以用于上下文名称,它们被不区分大小写地选中。
labels 控制是否执行changeset,这取决于运行时设置。任何字符串都可以用于标签名称,并且不区分大小写地选中它们。
runInTransaction 是否应该将changeset作为单个事务运行(如果可能的话)?默认值为true。
failOnError 如果在执行changeset时发生错误,迁移是否应该失败
objectQuotingStrategy 这控制了在生成的SQL中如何引用对象名,或者在对数据库的调用中如何使用对象名。不同的数据库对对象的名称执行不同的操作,例如Oracle将所有内容都转换为大写(除非使用引号)。有三个可能的值。默认值是LEGACY。三个配置的值: LEGACY - Same behavior as in Liquibase 2.0 QUOTE_ALL_OBJECTS - 每个对象都加上双引号 :person becomes “person”.QUOTE_ONLY_RESERVED_WORDS - 在保留关键字和可用列名上面加双引号
(2)可用的子标签
value description
comment 注释
preConditions 前置条件,例如做一些不可逆操作前的必要检查
<Any Refactoring Tag(s)> 要作为这个更改集的一部分运行的数据库更改
validCheckSum 添加一个校验和,不管数据库中存储了什么,它都被认为对这个changeset是有效的。主要用于需要更改changeset,并且不希望在已经运行了changeset的数据库上抛出错误(不推荐使用此过程)
rollback 描述如何回滚更改集的SQL语句或重构标记

着重讲一下rollback标签的示例:

<changeSet id="1" author="bob"><createTable tableName="testTable"><rollback>drop table testTable</rollback>
</changeSet>
123456
<changeSet id="1" author="bob"><createTable tableName="testTable"><rollback><dropTable tableName="testTable"/></rollback>
</changeSet>
123456
<changeSet id="2" author="bob"><dropTable tableName="testTable"/><rollback changeSetId="1" changeSetAuthor="bob"/>
</changeSet>
1234

这里发生了回滚,会调用id为1的changeSet 。

5.1.4.include标签

将change-logs拆分为易于管理的部分。

例如:

<?xml version="1.0" encoding="UTF-8"?><databaseChangeLogxmlns="http://www.liquibase.org/xml/ns/dbchangelog"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangeloghttp://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd"><include file="com/example/news/news.changelog.xml"/><include file="com/example/directory/directory.changelog.xml"/>
</databaseChangeLog>

可用的配置项:

Attribute Description
file 被引入的文件
relativeToChangelogFile 用文件的相对路径而不是classpath
context 向所有包含的changeSets追加上下文(使用AND)

Q.E.D.

liquibase的changelog详解相关推荐

  1. 【PHP】PHP5.4.0版本ChangeLog详解(上)

    前言 随着大量的框架使用composer和namespace,渐渐的线上环境也从之前的5.3变成了5.4或者5.5甚至5.6,随着7月份PHP7的发布,会有更多的公司采用新版本. 之前好久就想写这样的 ...

  2. numeric比较大小 数据库_Liquibase 数据库版本管理工具:3. changeSet 变更集详解

    上篇文章中详细了介绍了一下changelog 文件的使用,本篇文章将详细说一下 changeSet 变更集 中的细节,以及通常的使用方式 1.变更集分类 changeSet 分为 6类: add cr ...

  3. SpringBoot的配置详解application

    SpringBoot的配置文件application有两种文件格式,两种配置的内容是一致的,只是格式不一致. 1.application.properties 2.application.yml或者a ...

  4. [转]application.properties详解 --springBoot配置文件

    本文转载:http://blog.csdn.net/lpfsuperman/article/details/78287265###; # spring boot application.propert ...

  5. application.properties详解 --springBoot配置文件

    转载侵删:https://blog.csdn.net/lpfsuperman/article/details/78287265 以下为链接原文 # spring boot application.pr ...

  6. Linux 高可用(HA)集群之Pacemaker详解

    大纲 说明:本来我不想写这篇博文的,因为前几篇博文都有介绍pacemaker,但是我觉得还是得写一下,试想应该会有博友需要,特别是pacemaker 1.1.8(CentOS 6.4)以后,pacem ...

  7. RPM打包原理、示例、详解及备查

    原文地址:https://blog.csdn.net/qq_16542775/article/details/80961213 RPM(Redhat Package Manager)是用于Redhat ...

  8. iptables详解--转

    出处:http://yijiu.blog.51cto.com/433846/1356254 iptables详解 基本概念: 1.防火墙工作在主机边缘:对于进出本网络或者本主机的数据报文,根据事先设定 ...

  9. Tomcat原理详解和各种集群的实现

    注意:本篇博文涉及的知识内容如下,实验中所用的系统环境为RHEL6.4. 1.Java基础知识讲解 2.Tomcat的安装和实现 3.通过apache的mod_proxy模块代理并实现Tomcat负载 ...

最新文章

  1. [Unity WWW] 跨域访问解决方法
  2. 下列哪项不属于以太网交换机的特点_网络测试作业题
  3. Python3学习笔记01-环境安装和运行环境
  4. 视频直播技术详解(2)采集
  5. php循环读取mysql_PHP无限循环获取MySQL数据
  6. mysql5.7.11 linux_CentOS 7 中以命令行方式安装 MySQL 5.7.11 for Linux Generic 二进制版本教程详解...
  7. 20165223 week2测试补交与总结
  8. 如何创建_重庆市百科如何创建
  9. 解决IIS安装的问题:要求输入用户名和密码
  10. 2018美赛 A 题
  11. everything无法搜索刚插入的硬盘中的文件
  12. 计算机里的文档怎么设置密码,文件夹怎么设置密码,教您如何给电脑上文件夹设置密码...
  13. edge linux 下载软件,微软Edge浏览器Linux开发版
  14. 【图】爱情公寓里你最喜欢谁?爱情公寓3的投票,快来参加哦。
  15. 端游开发用什么技术可以让用户更短时间内体验游戏?端游分发...
  16. 6_1 系统安全分析与设计
  17. oracle中三元运算符,三目运算符简介 - ZICK_ZEON的个人空间 - OSCHINA - 中文开源技术交流社区...
  18. 「区块链+数字身份」:身份认证的新战场,让子弹再飞会儿
  19. 王者荣耀背后的实时大数据平台用了什么黑科技?
  20. 为什么在网络的最后用average pooling layer 代替FC

热门文章

  1. CSS设置 background-image透明度小技巧
  2. 基于cc3200开发
  3. 可达性分析算法中根节点有哪些
  4. pgpool读写分离,配置设置及调研
  5. Android Studio安装遇到的问题(最全)
  6. platform device和platform driver
  7. 电能减去热能计算机械能,力与运动机械能热能计算题
  8. win10搜索服务器文件慢,如何解决win10搜索速度很慢的情况呢?|win10加快系统搜索速度的方法...
  9. Dubbo源码解析-——服务引用
  10. Nginx基于IP的访问控制