`

通过liquibase将PostgreSQL数据库导入到H2数据库

    博客分类:
  • DB
阅读更多
1.背景
项目中使用的数据库是PostgreSQL,在做测试时,想使用H2代替。
2.问题
2.1 保留字:在PostgreSQL中使用了几个H2的保留字,例如 "end", "offset", "foreign",这些保留字是不能作为表的字段名。
2.2 字段类型:在PostgreSQL中double precision类型需要被替换成H2的float。
3.方法
liquibase提供一个ant任务:generateChangeLog,可以将PostgreSQL数据库中表,约束和数据都导出到一个xml文件中。然后通过liquibase根据导出的xml文件,在H2中生成数据库。
4.结果
生成xml文件,内容是liquibase的ChangeLog。

在使用generateChangeLog时,需要做一些扩展。
1.generateChangeLog任务
<generateChangeLog
	            outputFile="xxxxx\\structure.xml"
	            driver="org.postgresql.Driver"
	            url="jdbc:postgresql://localhost:5432/db"
	            username="name"
	            password="pass"
	            classpathref="classpath"
	    		loglevel="debug"
				databaseClass="xxx.ExtendPostgresDatabase"
	    		changeLogFile="xxxx\\structure.ext"
	    		diffTypes="tables, columns, views, indexes, sequences"
	            />

outputFile指定生成的文件,包含指定生成文件的liquibase.serializer.core.xml.XMLChangeLogSerializer。
databaseClass指定任务执行时数据库的类型。
changeLogFile指定生成的自定义文件,当changeLogFile指定时outputFile会被忽略。需要注册自定义的liquibase.serializer.ChangeLogSerializer。
diffTypes指定generateChangeLog任务执行时哪些数据库元素被导出。

2.扩展PostgresDatabase类

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import liquibase.database.core.PostgresDatabase;
import liquibase.database.typeconversion.TypeConverterFactory;
import liquibase.serializer.ChangeLogSerializerFactory;
import liquibase.snapshot.DatabaseSnapshotGeneratorFactory;

public class ExtendPostgresDatabase
    extends PostgresDatabase
{

    public static final List<String> reservedWords = Arrays.asList( new String[] { "end", "offset", "foreign" } );

    public static final List<String> ignoreTables = new ArrayList<String>();

    public static final List<String> ignoreIndexes = new ArrayList<String>();

    public static final List<String> ignorePrimaryKeys = new ArrayList<String>();

    public static final List<String> ignoreForeignKeys = new ArrayList<String>();

    public ExtendPostgresDatabase()
    {
        TypeConverterFactory.getInstance().register( new Postgres2H2TypeConverter() );//注册类型转换器,将Postgres的数据类型转换成H2
        ChangeLogSerializerFactory.getInstance().register( new ExtendXMLChangeLogSerializer() );//注册ChangeLog文件生成器
        DatabaseSnapshotGeneratorFactory.getInstance().register( new ExtendPostgresDatabaseSnapshotGenerator() );//注册数据库快照
    }

    @Override
    public boolean isReservedWord( String word )
    {
        boolean reservedWord = super.isReservedWord( word );
        if ( reservedWord )
        {
            return reservedWord;
        }

        return reservedWords.contains( word.toLowerCase() );
    }

}


3.扩展PostgresDatabaseSnapshotGenerator类


import java.util.Set;

import liquibase.database.Database;
import liquibase.database.structure.ForeignKey;
import liquibase.database.structure.Index;
import liquibase.database.structure.PrimaryKey;
import liquibase.database.structure.Table;
import liquibase.diff.DiffStatusListener;
import liquibase.exception.DatabaseException;
import liquibase.snapshot.DatabaseSnapshot;
import liquibase.snapshot.jvm.PostgresDatabaseSnapshotGenerator;

public class ExtendPostgresDatabaseSnapshotGenerator
    extends PostgresDatabaseSnapshotGenerator
{

    @Override
    public DatabaseSnapshot createSnapshot( Database database, String requestedSchema, Set<DiffStatusListener> listeners )
        throws DatabaseException
    {
        DatabaseSnapshot snapshot = super.createSnapshot( database, requestedSchema, listeners );

        //过滤掉不希望被导出的数据库元素
        for ( String key : ExtendPostgresDatabase.ignoreIndexes )
        {
            Index index = snapshot.getIndex( key );
            snapshot.getIndexes().remove( index );
        }
        for ( String key : ExtendPostgresDatabase.ignoreTables )
        {
            Table table = snapshot.getTable( key );
            snapshot.getTables().remove( table );
        }
        for ( String key : ExtendPostgresDatabase.ignorePrimaryKeys )
        {
            PrimaryKey primaryKey = snapshot.getPrimaryKey( key );
            snapshot.getPrimaryKeys().remove( primaryKey );
        }
        for ( String key : ExtendPostgresDatabase.ignoreForeignKeys )
        {
            ForeignKey foreignKey = snapshot.getForeignKey( key );
            snapshot.getForeignKeys().remove( foreignKey );
        }
        return snapshot;
    }

    @Override
    public boolean supports( Database database )
    {
        return database instanceof ExtendPostgresDatabase;
    }

    @Override
    public int getPriority( Database database )
    {
        return super.getPriority( database ) + 1;
    }

}


4.扩展XMLChangeLogSerializer类

import liquibase.change.ColumnConfig;
import liquibase.serializer.core.xml.XMLChangeLogSerializer;

import org.w3c.dom.Element;

public class ExtendXMLChangeLogSerializer
    extends XMLChangeLogSerializer
{

    @Override
    public String[] getValidFileExtensions()
    {
        return new String[] { "ext" };//配合generateChangeLog任务中指定的changeLogFile的后缀名
    }

    public Element createNode( ColumnConfig columnConfig )
    {
        //如果列的名字是保留字,需要加上转义符,否则在导入H2时会失败。        
        Element createNode = super.createNode( columnConfig );
        String tagName = createNode.getTagName();
        if ( tagName.equalsIgnoreCase( "column" ) )
        {
            String name = createNode.getAttribute( "name" );
            if(ExtendPostgresDatabase.reservedWords.contains(name.toLowerCase()))
            {
                createNode.setAttribute( "name", "\"" + name + "\"" );
            }
        }

        return createNode;

    }

}


5.扩展H2TypeConverter类

import liquibase.database.Database;
import liquibase.database.structure.Column;
import liquibase.database.typeconversion.core.H2TypeConverter;

public class Postgres2H2TypeConverter
    extends H2TypeConverter
{

    @Override
    public int getPriority()
    {
         return super.getPriority()+1;
    }

    @Override
    public boolean supports( Database database )
    {
        return database instanceof ExtendPostgresDatabase;
    }

    @Override
    public String convertToDatabaseTypeString( Column referenceColumn, Database database )
    {
        //将PostgreSQL的类型转换成H2类型
        if ( "LONGVARCHAR".equals( referenceColumn.getTypeName().toUpperCase() ) )
        {
            return "LONGVARCHAR";
        }

        if ( "FLOAT4".equals( referenceColumn.getTypeName().toUpperCase() ) )
        {
            return "FLOAT";
        }

        return super.convertToDatabaseTypeString( referenceColumn, database );
    }

}


分享到:
评论

相关推荐

    PostgreSQL数据库内核分析

    PostgreSQL数据库内核分析PostgreSQL数据库内核分析PostgreSQL数据库内核分析PostgreSQL数据库内核分析PostgreSQL数据库内核分析PostgreSQL数据库内核分析PostgreSQL数据库内核分析PostgreSQL数据库内核分析...

    Python编写PostgreSQL数据库结构比对程序源代码

    PostgreSQL是一种流行的开源关系型数据库管理系统,以其强大的功能和稳定性受到广大开发者喜爱。Python作为一种易学且功能丰富的编程语言,常用于与数据库交互,进行数据处理和自动化任务。本主题将围绕使用Python...

    PostgreSQL数据库内核分析.pdf

    PostgreSQL数据库内核分析.pdf

    C# 操作PostgreSQL 数据库

    本文将深入探讨如何使用C#来操作PostgreSQL数据库。 首先,我们需要安装必要的库以在C#中与PostgreSQL进行交互。Npgsql是.NET Framework和.NET Core下的一个开源驱动,它允许C#应用程序无缝连接到PostgreSQL数据库...

    连接postgresql数据库需要的jar包

    在Java编程中,连接到PostgreSQL数据库通常需要特定的驱动程序,这个驱动程序通常是以JAR(Java Archive)文件的形式存在。"连接postgresql数据库需要的jar包"指的是用于建立Java应用程序与PostgreSQL数据库之间通信...

    PostgreSQL数据库内核分析 清晰版

    PostgreSQL数据库内核分析 清晰版,完整415页

    PostgreSQL数据库内核分析 完整版

    《PostgreSQL数据库内核分析》彭智勇 完整版44M

    一套C#与PostgreSQL数据库完美结合的实例

    本套程序是在VS2005下C#开发,利用PostgreSQL作为数据库。 本程序的重点是如何利用C#对PostgreSQL数据库...将App_Data下的数据库文件导入到PostgreSQL 8.3版里面,库名为:HYGL 然后修改web.config中的配置即可使用

    如何恢复PostgreSQL数据库

    下面将详细介绍如何恢复 PostgreSQL 数据库。 一、备份和恢复 PostgreSQL 数据库 恢复 PostgreSQL 数据库通常是通过备份和恢复实现的。在特殊情况下,系统故障,PostgreSQL 数据库无法打开,这时候只有求助与存放...

    postgresql10数据库生成文档工具

    4. **数据库转换**:数据库转换通常指将数据或数据库结构从一种格式或平台迁移到另一种。在本工具中,可能涉及的是将PostgreSQL 10的数据库结构转换成易于阅读和共享的文档格式。 5. **一键生成**:一键生成功能...

    asp连接postgresql数据库

    asp连接postgresql数据库 的源码

    nacos适配postgresql数据库

    1.nacos服务,适配postgresql数据库。 2.提供nacos,postgresql的创建nacos数据库脚本。 3.nacos/conf/nacos-pg.sql数据库脚本文件。 4.nacos版本1.4.2。

    Python-一个PostgreSQL数据库迁移工具

    数据库迁移是指将数据库从一个状态迁移到另一个状态的过程,通常涉及数据库结构的更改,如添加、删除或修改表、字段、索引等。在软件开发中,随着应用程序的发展,数据库结构也需要随之调整,这就需要数据库迁移工具...

    postgresql数据库定时备份脚本(linux)

    1. **使用pg_restore**:将.sql文件恢复到新的数据库。 2. **使用pg_basebackup恢复**:直接替换现有数据目录或恢复到新的位置。 确保定期检查备份的完整性和可恢复性,以验证备份策略的有效性。在生产环境中,还应...

    postgresql数据库备份和恢复

    当需要恢复PostgreSQL数据库时,psql命令行工具可以被用来重新导入备份文件到数据库中。该工具不仅可以执行SQL语句,也可以用来恢复数据库备份。恢复操作的命令如下: ``` psql -h &lt;host&gt; -U &lt;username&gt; -d ...

    将excal批量数据插入到postgresql数据库(目前实现字符串拼接的方式)

    在本教程中,我们将聚焦于如何将Excel数据批量导入到PostgreSQL数据库,特别关注一种常见的方法——通过字符串拼接的方式。PostgreSQL是一个功能强大的开源关系型数据库管理系统,而Excel则是广泛使用的电子表格工具...

    Matlab与PostgreSQL数据库的连接

    在 Matlab 中,使用 JDBC 连接 PostgreSQL 数据库需要下载对应的 JDBC 驱动程序,然后将其添加到 Matlab 的环境中。 知识点:PostgreSQL 的 JDBC 驱动程序 PostgreSQL 的 JDBC 驱动程序可以从官方网站下载,例如...

    MyBatis通过 JDBC连接 PostgreSQL数据库 最小例子

    在本文中,我们将深入探讨如何使用MyBatis框架通过JDBC连接PostgreSQL数据库,构建一个最小的示例项目。MyBatis是一个轻量级的Java持久层框架,它简化了数据库操作,允许开发者将SQL语句直接嵌入到Java代码中,提供...

    Postgresql数据库集群在主题网络爬虫的应用.pdf

    通过将PostgreSQL数据库集群技术应用于主题网络爬虫,不仅能够有效解决大规模信息存储的问题,还能通过引入缓存技术进一步提升爬虫系统的整体性能。 #### 引言 搜索引擎作为互联网时代最重要的信息检索工具之一,...

Global site tag (gtag.js) - Google Analytics