PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Hibernasi UUID dengan PostgreSQL dan SQL Server

Saya memiliki persyaratan serupa, tetapi saya juga ingin menggunakan generasi DDL Hibernate dan memastikan bahwa SQL Server menghasilkan tipe pengenal unik, dan juga ingin mendukung hsqldb untuk pengujian unit. Untuk menggunakan UUID di SQL Server, Anda pasti ingin melalui string bukan biner , karena representasi biner di SQL Server adalah untuk GUID yang berbeda dari UUID. Lihat misalnya Representasi berbeda dari UUID di Java Hibernate dan SQL Server

Anda dapat membuat pemetaan yang benar dan menghasilkan sql yang benar untuk SQL Server dengan:

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

Dan ini berfungsi sebagaimana adanya, tetapi sayangnya tidak ada cara di Hibernate untuk memiliki definisi kolom yang berbeda untuk database yang berbeda, jadi ini akan gagal pada apa pun selain SQL Server.

Jadi, Anda harus pergi jauh. Ini semua untuk Hibernate 4.3:

  1. Daftarkan jenis sql GUID baru di SQLServerDialect yang diganti, dan gunakan dialek ini sebagai ganti yang dasar

    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. Buat UUIDCustomType pembungkus yang berperilaku mirip dengan UUIDCharType bawaan tetapi mendelegasikan tergantung pada tipe database. Anda perlu memanggil init(databaseType) sebelum Konfigurasi hibernasi. Mungkin dialek khusus bisa melakukannya, tapi saya menyebutnya di startup aplikasi Spring saya.

DatabaseType adalah enum yang sudah saya set berdasarkan konfigurasi sistem, modifikasi sesuai selera menggunakan kelas dialek atau string atau apa pun.

Ini adalah variasi dari apa yang dijelaskan di 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. Daftarkan tipe kustom di lokasi yang akan diambil oleh Hibernate (Saya memiliki kelas dasar yang sama untuk semua entitas). Saya mendaftarkannya menggunakan defaultForType =UUID.class sehingga semua UUID menggunakannya, yang berarti saya tidak perlu membubuhi keterangan properti UUID sama sekali.

    @TypeDefs( {
            @TypeDef( name = "uuid-custom", typeClass = UUIDCustomType.class, defaultForType = UUID.class )
    } )
    public class BaseEntityWithId { 

Peringatan:sebenarnya tidak diuji dengan postgres, tetapi bekerja dengan baik untuk hsqldb dan sql server di Hibernate 4.3.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. hibernasi dengan c3p0:createClob() belum diimplementasikan

  2. Di PostgreSQL, bagaimana cara memasukkan data dengan perintah COPY?

  3. Bagaimana to_char() Bekerja di PostgreSQL

  4. Mengelola Ketersediaan Tinggi di PostgreSQL – Bagian II:Manajer Replikasi

  5. Apakah spesifikasi JDBC mencegah '?' dari digunakan sebagai operator (di luar tanda kutip)?