sql >> Database >  >> RDS >> PostgreSQL

Slaapstand UUID met PostgreSQL en SQL Server

Ik had vergelijkbare vereisten, maar ik wilde ook Hibernate DDL-generatie gebruiken en ervoor zorgen dat SQL Server een uniqueidentifier-type genereerde, en wilde ook hsqldb ondersteunen voor het testen van eenheden. Om UUID's in SQL Server te gebruiken, wilt u absoluut door strings gaan die niet binair zijn , aangezien de binaire weergave in SQL Server voor een GUID is die verschilt van een UUID. Zie bijvoorbeeld Verschillende weergave van UUID in Java Hibernate en SQL Server

U kunt de juiste mapping maken en de juiste sql voor SQL Server genereren met:

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

En dit werkt gewoon zoals het is, maar helaas is er geen manier in Hibernate om verschillende columnDefinities voor verschillende databases te hebben, dus dit zal mislukken op iets anders dan SQL Server.

Je moet dus een heel eind lopen. Dit is alles voor Hibernate 4.3:

  1. Registreer een nieuw GUID sql-type in een overschreven SQLServerDialect en gebruik dit dialect in plaats van het basisdialect

    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. Maak een wrapper UUIDCustomType die vergelijkbaar is met het ingebouwde UUIDCharType, maar delegeert afhankelijk van het databasetype. U moet init(databaseType) voor . aanroepen Slaapstand configuratie. Misschien zou het aangepaste dialect het kunnen doen, maar ik noem dit in mijn Spring-app-opstart.

DatabaseType was een opsomming die ik al had en die is ingesteld op basis van systeemconfiguratie, pas het naar smaak aan met behulp van een dialectklasse of string of wat dan ook.

Dit is een variatie op wat wordt beschreven op 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. Registreer het aangepaste type op een locatie die Hibernate zal ophalen (ik heb een gemeenschappelijke basisklasse voor alle entiteiten). Ik registreer het met defaultForType =UUID.class zodat alle UUID's het gebruiken, wat betekent dat ik helemaal geen UUID-eigenschappen hoef te annoteren.

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

Waarschuwing:niet echt getest met postgres, maar werkt prima voor hsqldb en sql-server op Hibernate 4.3.



  1. Vind records waar join niet bestaat

  2. Gegevens opslaan in MySQL als JSON

  3. Laatst uitgevoerde zoekopdrachten voor een specifieke database

  4. De beste manier om json te cachen