使数据库结构与应用程序保持同步
每个项目都存在一个小问题--使数据库结构与应用程序保持同步。也就是说,当您的代码依赖于新的表或列时,该表/列必须出现在数据库中。当存在多个环境时,这尤其是一个问题,在此环境上部署代码(生产、阶段、集成、本地),因为通常需要执行额外的步骤才能更新数据库模式。
实现预期效果的最快方法是每次代码需要新的数据库元素(或者不再需要数据库元素)时提供SQL升级脚本。但这很繁琐,因为这些SQL脚本必须在部署到的每个环境上手动执行。自动化这个过程是通过几个框架实现的,因此您不需要这
为什么我们真的需要这样的解决方案呢?我们的目标是频繁地、一键地部署到暂存和生产环境中。如果没有自动同步数据库的方法,我们就无法做到这一点(否则会有缺少的列,或者过时的非空列将阻止数据插入)。有时,我们可能需要恢复一个版本,并且必须相应地回滚数据库更改。虽然您可以在本地开发时删除并重新创建模式,但是在生产中不能这样做。
Rails开发人员会正确地说:“我们已经有很长一段时间了。”的确似乎是将应用程序代码与数据库架构保持同步的理想实现。但我不得不为Java项目选择一种技术。实际上,这是一个grails项目,即使,我选择了另一个名为Liquibase的插件(注意:Grails插件是在液化库的基础上构建的)。我将解释如何在单独的文章中使用JPA,但它似乎具备Rails提供的所有功能:用于升级的人读(Xml)格式、自动回滚脚本执行以及基于数据库差异生成升级脚本的工具。
事实上,我从来没有在我的个人项目中使用过类似清算的解决方案。我甚至在生产中都使用Hibernate hbm2ddl.Auto,有时还会手动修复。是的,对于大型项目来说,这不是一个可行的解决方案,而且存在风险。实际上,没有人建议在生产中使用“hbm2ddl.auto”,因为它并不完美,可能意味着丢失数据或停机时间。对于那些不熟悉Hibernate的人,hbm2ddl.Auto是一个配置开关,它使Hibernate(和ORM框架)创建对应于实体映射的表和列。从某种意义上说,它是一种将应用程序代码与数据库结构自动同步的方法。它可以做到这一点,因为我们在带注释的POJO(实体)中有了预期的数据库结构,这种结构可以精确地定义我们需要的表、列和键。但是,正如我所说的,它不建议用于生产(建议将其设置为“验证”,以便它可以验证数据库和代码是否同步)。
https://movie.douban.com/review/14021703/
但我是个理想主义者。我想要比一个好的迁移工具更好的东西,比如液化库。我们有先决条件--这是代码定义所需模式的结构化方式。这就是JPA注释(带有一些供应商扩展)。我们只需要一个像手动创建SQL升级脚本那样工作的工具。它需要:
- 创建表、列、索引、外键
- 删除表、列、索引、外键
- 更改表、列、索引、外键
- 修复结构更改之前/之后的数据
- 确保没有丢失数据
https://movie.douban.com/review/14016002/
AUTO只做第一个,也可以做第四个。实现“DROP”和“ALTERT”功能相对容易。如何确保没有丢失数据?每当删除列或表时,都会创建一个新的临时表(例如,前缀为_HBM_temp),该表存储来自该列/表的数据。如果发生了数据不应该被删除的情况,您可以将其取回。否则,您可以偶尔清理所有临时表。我看不出这种方法有什么明显的问题,它将节省大量的时间、精力和错误。
在这个主题上,我不能跳过造成这种复杂性的主要原因--关系数据库有一个僵化的模式这一事实。另一方面,NoSQL数据库大多没有模式。它消除了由于缺少列或表而产生的异常--它们在数据库中自动“出现”。但是,未使用的字段仍然存在并污染了数据库,您应该手动清理数据库。没有任何数据库强加的约束意味着它们应该在应用程序代码中处理。所以,我们有一个权衡(和往常一样)。
总之,为了修复数据库,必须避免手动执行SQL脚本。始终以应用程序为主要目标,并使其他一切(模式)遵循。这种情况不可能总是发生(例如,如果您需要数据库触发器和存储过程,或者您有多个应用程序使用相同的数据库,无法共享它们的代码库),但至少要将这些脚本与代码放在同一个存储库中,并使快速部署到任何环境成为可能,并且所涉及的手动任务尽可能少。

浙公网安备 33010602011771号