这几天工作需要使用 Apollo 配置中心. Apollo 唯一的依赖是 MySQL 数据库, 然而公司只有 Oracle 数据库资源. 这里 https://github.com/vanpersl/apollo/tree/db-oracle 有一个 Oracle 适配改动的分支, 但是它是基于 0.8.0 版本的 Apollo. 看着 Apollo 官方文档上各种特性都只有 1.0.0 以上版本才有, 我决定基于当前最新版本 (1.2.0) 自己改一波.
基础
在开始改动前我们需要了解 Apollo 工程的整体结构, 以及调试启动的方法. 建议本地先搭建个 MySQL 库, 然后把 Apollo 跑起来看看. 官方对此有详细的文档.
另外, 从 MySQL 到 Oracle, 一个比较大的问题是 Apollo 中很多表名, 字段名和 Oracle 的关键字有冲突, 导致无法在 Oracle 建表. 这个问题可以使用双引号来解决. 我们知道, Oracle 的 SQL 语句在解释时会把所有的字符都转为大写 (字符串常量除外), 所以我们一般认为 Oracle 的 SQL 语法不区分大小写. 比如说我可以用如下 SQL 建表:
create TaBle aPplicAtiOn(...);
最终我们会得到一张名为 APPLICATION 的表. 在一些情况下, 我们会需要区分大小写的表名, 这时候我们可以在建表时用双引号将表名括起来:
create TaBle "aPplicAtiOn"(...);
这样, 我们就真正得到了名为 aPplicAtiOn 的表了. 同理, 字段名, 同名等 Oracle 对象也都可以用双引号来区分大小写. 关于 Oracle 双引号, 这里有更多的讲解.
Oracle 适配改动
下面的改动大部分是参考已有的 vanpersl/apollo 基于 0.8.0 的 Oracle 版本的代码. 这里是他的修改内容.
总体来说改动量不大. 我大约花了一天的时间完成了整个改动. 下面是改动步骤.
准备数据库用户
准备两个 Oracle 用户 (Oracle 用户相当于 MySQL 的库), 分别用于存放配置数据 (假设这个用户叫 ApolloConfig) 和管理数据 (假设这个用户叫 ApolloPortal). 配置数据和管理数据有很多表名是相同的, 所以必须使用两个用户. 你也可以使用两个现有的用户, 但是要注意不要和现有的表冲突了.
使用 Oracle 的 SQL 脚本建表. 这里是我整理后的两个 SQL 脚本, ApolloConfig 用户执行 apolloconfigdb.sql 脚本, ApolloPortal 用户执行 apolloportaldb.sql 脚本.
Apollo 工程加入 ojdbc 的依赖
我测试了 ojdbc6 和 ojdbc7 是可以使用的, 而 ojdbc12 则会报版本太低的错误. 我最后使用的 ojdbc6, 因为我最后测试的是 ojdbc6 就懒得再换了.
另外, 我在做这一步的时候发现使用 Maven 源的 ojdbc 包是无法启动项目的. 只能到 Oracle 官网下载 jar 包, 然后本地引用. ojdbc 的依赖添加到 parent 项目和 apollo-common 项目.
修改数据库连接配置
新建好 Oracle 的库后, 将 Apollo 配置中原本 MySQL 的连接配置改为 Oracle 的连接配置 -- 注意, 根据你的部署方式, 可能需要修改两处或者三处的连接配置.
- spring.datasource.url=jdbc:oracle:thin:@{
- ip
- }:{
- port
- }:{
- db
- }
- spring.datasource.username={
- ApolloConfig|ApolloPortal
- }
- spring.datasource.password={
- password
- }
添加 Oracle 配置.
这些配置改动在 apollo-common 的 application.properties 配置文件.
添加配置
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
指定使用 Oracle 驱动
如果你的 Oracle 版本在 11c 以下 (比如 10g 或者 11g), 那么还需要添加
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
. 否则 Hibernate 会生成
fetch first ? rows only
之类的 11c 才支持的语句导致 SQL 执行错误.
其他的连接池之类的配置.
Sequence
Apollo 的表使用的自增 ID 作为主键. Oracle 没有直接支持自增 ID 的功能, 必须通过 Sequence 实现. 在建表的 SQL 里已为两个库分别建了名为 ID_SEQ 的 Sequence. 代码中所有的 Entity 类的 id 属性都要加上 GeneratedValue 和 SequenceGenerator 的配置. Apollo 的代码中大部分的 Entity 类是继承自一个 BaseEntity 基类的, 所以要修改的地方并不多.
这几个类需要修改: BaseEntity,ReleaseMessage,InstanceConfig,Instance,UserPO,ConsumerAudit
如下添加 GeneratedValue 和 SequenceGenerator 两行:
- public abstract class BaseEntity {
- @Id
- @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
- @SequenceGenerator(name = "sequence", sequenceName = "ID_SEQ", allocationSize = 1)
- @Column(name = "Id")
- private long id;
- ...
- }
Oracle 关键字的问题
这部分的改动最多, 也最枯燥. 合理利用 IDE 的 replace 功能可以极大的提高修改效率.
由于原本 MySQL 的表名列名用了很多 Oracle 的关键字, 所以转到 Oracle 时所有的表名列名都用双引号括起来. 可在 apollo-commom 的
application-properties
配置中加上:
- spring.jpa.hibernate.globally_quoted_identifiers=true
- spring.jpa.properties.hibernate.globally_quoted_identifiers=true
这样 Hibernate 的 ORM 生成 SQL 语句时就会自动给表名列名都加上双引号.
另外, 一些在注解里的类 SQL 语句用到的字段要手工加上双引号. 大概有以下这些地方:
@SQLDelete 和 @Where 的地方
AuthConfiguration.java 中有一堆直接写 SQL 的
所有的 isDeleted 和 id 都要改首字母大写
Namespace 有个 appId,Item 有个 key,value,comment,GreyReleaseRule 有 appId 和 releaseId
其他我还没发现的犄角旮旯
成果
我最后修改的结果上传在这里: https://github.com/sKabYY/apollo .
目前已经平稳运行. 后面如果有 bug 修改或者升级也会更新上去.
来源: http://www.bubuko.com/infodetail-2938767.html