Liquibase:changeset自动生成ID

5

如何使用liquibase自动生成更改集的ID?

我不想手动设置每个更改集的ID,是否有自动设置的方法?


不,没有(至少没有内置的)。 - user330315
我怀疑那样做行不通。原因如下:Liquibase可以创建/更新/等你的模式。为此,它执行你放入其changeset文件中的内容。然后,它将已执行的更改存储在自己的表中,以了解它已经完成了哪些工作。如果每次重新启动应用程序时都生成一个随机ID,它将永远无法弄清楚已经运行了哪些更改和哪些没有运行。唯一的替代方案(我能想到的)是深入研究liquibase源代码,并使ID由changeset的哈希值生成(即使这样也可能会导致冲突)。如果我误解了你的问题,请让我知道。 - pandaadb
问题 - 您目前是如何创建您的变更集的? - SteveDonie
非常感谢您的回复。@Stevedonie 我在一个更改日志中创建了所有更改集。 - jam
1
不,我的意思是您创建更改集使用的确切步骤是什么?您使用Liquibase命令吗?还是使用记事本?通常,在报告任何问题时,包括三个方面非常有帮助 - 1-这些是我采取的步骤,2-实际发生了什么,3-我希望发生什么。但是您没有涵盖其中任何一个。 - SteveDonie
2个回答

2

我认为生成的ID并不是一个好主意。原因是Liquibase使用changeSet ID来计算校验和(除了作者和文件名)。所以,如果您在其他变更集之间插入一个变更集,则所有后续变更集的校验和都会改变,您将收到大量警告/错误。

无论如何,如果您仍然想生成ID,我可以想到以下解决方案:

  1. 创建自己的ChangeLogParser

如果您自己解析ChangeLog,则可以自由地按照自己的方式生成ID。缺点是您必须为changeLog提供自定义XML模式。Liquibase的模式对changeSet ID有约束(必填)。使用新模式,您可能需要对解析器进行大量调整。或者,您可以选择其他changeLog格式(YAML、JSON、Groovy)。它们的解析器可能更容易定制,因为它们不需要该模式定义。

  1. 进行一些预处理

您可以编写一个简单的XSLT(XML转换),从没有ID的文件中生成具有changeSet ID的changeLog。

使用时间戳作为ID。这是我的建议。虽然它并没有按照你的要求来解决问题,但它很简单、一致,并提供了额外的信息,同时也是其他数据库迁移工具的良好实践http://www.jeremyjarrell.com/using-flyway-db-with-distributed-version-control/

1
我编写了一个Python脚本来为Liquibase changelogs生成唯一的ID。

请注意!

在开发或准备发布changelog时

  • 当您控制目标数据库的校验和时
  • 或者当changelog已经部署时,请生成ID。

不要生成ID - 当changelog已经部署时。

"""
###############################################################################
Purpose: Generate unique subsequent IDs into Liquibase changelogs
###############################################################################

Args:
    param1:     Full Windows path changelog directory (optional) 
                OR
                --inplace: directly process changelogs (optional) 

    By default, XML files in the current directory are processed.

Returns:
    In case of success, the output path is returned to stdout. 
    Otherwise, we crash and drag the system into mordor.

    If you feel like wasting time you can: 
        a) port path handling to *nix 
        b) handle any obscure exceptions 
        c) add Unicode support (for better entertainment)

Dependencies:
    Besides Python 3, in order to preserve XML comments, I had to use lxml 
    instead of the stock ElementTree parser. 
    Install lxml:

    $ pip install lxml

    Proxy clusterfuck? Don't panic! Simply download a .whl package from: 
    https://pypi.org/project/lxml/#files and install with pip.

Bugs:
    Changesets having id="0" are ignored. Usually, these do not occur.    

Author:
    Tobias Bräutigam 

Versions:
    0.0.1 - re based, deprecated
    0.0.2 - parse XML with lxml, CURRENT 
"""

import datetime
import sys
import os
from pathlib import Path, PureWindowsPath

try:    
    import lxml.etree as ET
except ImportError as error:
    print (''' 
    Error: module lxml is missing.
    Please install it:

    pip install lxml
    ''')
    exit()

# Process arguments
prefix = '' # hold separator, if needed 
outdir = 'out'

try: sys.argv[1]
except: pass
else:
    if sys.argv[1] == '--inplace':
        outdir = ''
    else:                
        prefix = outdir + '//'
        # accept Windows path syntax
        inpath = PureWindowsPath(sys.argv[1]) 
        # convert path format
        inpath = Path(inpath) 
        os.chdir(inpath) 
        try: os.mkdir(outdir)
        except: pass
        filelist = [ f for f in os.listdir(outdir) ]
        for f in filelist: os.remove(os.path.join(outdir, f))

# Parse XML, generate IDs, write file 
def parseX(filename,prefix):    
    cnt = 0    
    print (filename)
    tree = ET.parse(filename)
    for node in tree.getiterator():
        if int(node.attrib.get('id', 0)):                        
            now = datetime.datetime.now()            
            node.attrib['id'] = str(int(now.strftime("%H%M%S%f"))+cnt*37)
            cnt = cnt + 1 
    root = tree.getroot()
    # NS URL element name is '' for Etree, lxml requires at least one character
    ET.register_namespace('x', u'http://www.liquibase.org/xml/ns/dbchangelog') 
    tree = ET.ElementTree(root)        
    tree.write(prefix + filename, encoding='utf-8', xml_declaration=True)
    print(str(cnt) +' ID(s) generated.')

# Process files
print('\n')
items = 0
for infile in os.listdir('.'):
    if (infile.lower().endswith('.xml')) == True:      
        parseX(infile,prefix)
        items=items+1

# Message
print('\n' + str(items) + ' file(s) processed.\n\n')
if items > 0:
    print('Output was written to: \n\n')    
    print(str(os.getcwd()) + '\\' + outdir + '\n')


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接