sql >> Database teknologi >  >> RDS >> PostgreSQL

Dvale UUID med PostgreSQL og SQL Server

Jeg havde lignende krav, men jeg ville også bruge Hibernate DDL-generering og sikre mig, at SQL Server genererede en unik identifikatortype, og jeg ville også understøtte hsqldb til enhedstestning. For at bruge UUID'er i SQL Server vil du helt sikkert gå gennem strenge, ikke binære , da den binære repræsentation i SQL Server er for en GUID, der er forskellig fra en UUID. Se for eksempel Forskellig repræsentation af UUID i Java Hibernate og SQL Server

Du kan oprette den korrekte mapping og generere den korrekte sql til SQL Server med:

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

Og dette fungerer bare som det er, men desværre er der ingen måde i Hibernate at have forskellige kolonnedefinitioner for forskellige databaser, så dette vil fejle på alt andet end SQL Server.

Så du skal gå den lange vej rundt. Det hele er til Hibernate 4.3:

  1. Registrer en ny GUID sql-type i en tilsidesat SQLServerDialect, og brug denne dialekt i stedet for basisdialekten

    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. Opret en wrapper UUIDCustomType, der opfører sig på samme måde som den indbyggede UUIDCharType, men delegerer afhængigt af databasetypen. Du skal kalde init(databaseType) før Dvale konfiguration. Måske kunne den tilpassede dialekt gøre det, men jeg kalder dette i min Spring-app-opstart.

DatabaseType var en enum, jeg allerede havde, og som er indstillet baseret på systemkonfiguration, modificer den efter smag ved hjælp af en dialektklasse eller streng eller hvad som helst.

Dette er en variation af det, der er beskrevet på 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. Registrer den tilpassede type på et sted, som Hibernate vil hente (jeg har en fælles basisklasse for alle enheder). Jeg registrerer det ved hjælp af defaultForType =UUID.class, så alle UUID'er bruger det, hvilket betyder, at jeg slet ikke behøver at annotere UUID-egenskaber.

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

Advarsel:faktisk ikke testet med postgres, men fungerer godt til hsqldb og sql server på Hibernate 4.3.



  1. Forespørgsel for at kontrollere tabelstørrelsen i Oracle-databasen

  2. Indsæt i flere tabeller i én forespørgsel

  3. Tilføj valutategn £, $ til visse felter ORACLE

  4. Sådan omdøbes et kolonnenavn eller tabelnavn i SQL Server - SQL Server / T-SQL selvstudie del 36