sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLとSQLServerでUUIDを休止状態にする

    同様の要件がありましたが、Hibernate DDL生成を使用して、SQL Serverが一意の識別子タイプを生成することを確認し、ユニットテスト用のhsqldbもサポートしたいと考えていました。SQLServerでUUIDを使用するには、バイナリではなく文字列を使用する必要があります。 、SQL Serverのバイナリ表現は、UUIDとは異なるGUID用であるため。たとえば、JavaHibernateとSQLServerでのUUIDの異なる表現を参照してください

    次のコマンドを使用して、正しいマッピングを作成し、SQLServerの正しいSQLを生成できます。

    @Type(type = "uuid-char")
    @Column(columnDefinition="uniqueidentifier")
    public UUID getUuid()
    

    これはそのまま機能しますが、残念ながら、Hibernateにはデータベースごとに異なるcolumnDefinitionsを設定する方法がないため、SQLServer以外では失敗します。

    だから、あなたは長い道のりを歩かなければなりません。これはすべてHibernate4.3の場合です:

    1. オーバーライドされたSQLServerDialectに新しいGUIDSQLタイプを登録し、ベースの方言の代わりにこの方言を使用します
    
        public class SQLServer2008UnicodeDialect extends SQLServer2008Dialect
        {
            public SQLServer2008UnicodeDialect() 
            {
                // the const is from the MS JDBC driver, the value is -145
                registerColumnType( microsoft.sql.Types.GUID, "uniqueidentifier" ); 
    
                // etc. Bonus hint: I also remap all the varchar types to nvarchar while I'm at it, like so:
                registerColumnType( Types.CLOB, "nvarchar(MAX)" );
                registerColumnType( Types.LONGVARCHAR, "nvarchar(MAX)" );
                registerColumnType( Types.LONGNVARCHAR, "nvarchar(MAX)" );
                registerColumnType( Types.VARCHAR, "nvarchar(MAX)" );
                registerColumnType( Types.VARCHAR, 8000, "nvarchar($l)" );
            }
         }
    
    1. 組み込みのUUIDCharTypeと同様に動作するが、データベースの種類に応じて委任するラッパーUUIDCustomTypeを作成します。 前にinit(databaseType)を呼び出す必要があります Hibernate構成。カスタム方言でそれができるかもしれませんが、Springアプリのスタートアップでこれを呼び出します。

    DatabaseTypeは、システム構成に基づいて設定された列挙型であり、方言クラスや文字列などを使用して好みに合わせて変更します。

    これは、https://zorq.net/b/2012/04/21/switching-hibernates-uuid-type-mapping-per-database/

    で説明されているもののバリエーションです。
    public enum DatabaseType
    {
        hsqldb,
        sqlserver,
        mysql,
        postgres
    }
    
    public class UUIDCustomType extends AbstractSingleColumnStandardBasicType<UUID> implements LiteralType<UUID>
    {
        private static final long serialVersionUID = 1L;
    
        private static SqlTypeDescriptor SQL_DESCRIPTOR;
        private static JavaTypeDescriptor<UUID> TYPE_DESCRIPTOR;
    
        public static void init( DatabaseType databaseType )
        {
            if ( databaseType == DatabaseType.sqlserver )
            {
                SQL_DESCRIPTOR = SqlServerUUIDTypeDescriptor.INSTANCE;
            }
            else if ( databaseType == DatabaseType.postgres  )
            {
                SQL_DESCRIPTOR = PostgresUUIDType.PostgresUUIDSqlTypeDescriptor.INSTANCE;
            }
            else
            {
                SQL_DESCRIPTOR = VarcharTypeDescriptor.INSTANCE;
            }
    
            TYPE_DESCRIPTOR = UUIDTypeDescriptor.INSTANCE;
        }
    
        public UUIDCustomType()
        {
            super( SQL_DESCRIPTOR, TYPE_DESCRIPTOR );
        }
    
        @Override
        public String getName()
        {
            return "uuid-custom";
        }
    
        @Override
        public String objectToSQLString( UUID value, Dialect dialect ) throws Exception
        {
            return StringType.INSTANCE.objectToSQLString( value.toString(), dialect );
        }
    
        public static class SqlServerUUIDTypeDescriptor extends VarcharTypeDescriptor
        {
            private static final long serialVersionUID = 1L;
    
            public static final SqlServerUUIDTypeDescriptor INSTANCE = new SqlServerUUIDTypeDescriptor();
    
            public SqlServerUUIDTypeDescriptor()
            {
            }
    
            @Override
            public int getSqlType()
            {
                return microsoft.sql.Types.GUID;
            }
        }
    }
    
    1. Hibernateが取得する場所にカスタムタイプを登録します(すべてのエンティティに共通の基本クラスがあります)。 defaultForType =UUID.classを使用して登録し、すべてのUUIDがそれを使用するようにします。つまり、UUIDプロパティに注釈を付ける必要はまったくありません。
    
        @TypeDefs( {
                @TypeDef( name = "uuid-custom", typeClass = UUIDCustomType.class, defaultForType = UUID.class )
        } )
        public class BaseEntityWithId { 
    

    警告:実際にはpostgresでテストされていませんが、Hibernate4.3上のhsqldbおよびsqlサーバーでうまく機能しています。



    1. Postgresタイムスタンプクエリ範囲を最適化する

    2. TempDBの最適化:ボトルネックとパフォーマンスの問題の回避

    3. contains()を使用するときに2100パラメーター制限(SQL Server)に達する

    4. リアルタイムアプリとは何ですか?