gpt4 book ai didi

java - 使用 PostgreSQL 和 SQL Server hibernate UUID

转载 作者:搜寻专家 更新时间:2023-11-01 02:58:53 26 4
gpt4 key购买 nike

我有一个应用程序,我想在 PostgreSQL 和 SQL Server 上运行。我想使用 java.util.UUID 作为 ID。

我在 SQL Server 中将我的列定义为

id  UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE

我在 PostgreSQL 中将我的列定义为

id  UUID NOT NULL

列在我的 JPA 实体中定义为

@Id
@Column(name = "id")
public UUID getId() {
return id;
}

这适用于 PostgreSQL,因为它将 UUID 传递给 PostgreSQL JDBC 驱动程序。这种类型适用于 SQL Server,因为 Hibernate 在将 UUID 发送到 SQL Server 之前将其转换为二进制形式。 Unfortunately the binary format is slightly different ,导致 GUID 的字符串表示形式(例如,当使用 SSMS 查看它们时)不同,这至少会造成混淆。

这可以在 SQL Server 中通过将列的类型更改为 uuid-char 来解决

@Id
@Type(type = "uuid-char")
@Column(name = "id")
public UUID getId() {
return id;
}

但是它在 PostgreSQL 中不再有效,因为在 Postgres 中没有从 varchar 到 uuid 的隐式映射。

Some people suggest更改生成器以生成 guid。这在 Postgres 中不起作用,因为在 PostgreSQL94Dialect 中不支持它。

为两个数据库创建这个词的最优雅的解决方案是什么?我正在考虑通过从 UUID 到二进制的自定义转换为 SQLServer 创建我自己的方言,但我不确定这是要走的路。

最佳答案

我也有类似的需求,但我也想使用Hibernate DDL生成,确保SQL Server生成uniqueidentifier类型,同时也想支持hsqldb进行单元测试。要在 SQL Server 中使用 UUID,您肯定希望通过字符串而不是二进制,因为 SQL Server 中的二进制表示是针对不同于 UUID 的 GUID。参见示例 Different representation of UUID in Java Hibernate and SQL Server

您可以创建正确的映射并为 SQL Server 生成正确的 sql:

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

这只是按原样工作,但不幸的是,在 Hibernate 中没有办法为不同的数据库设置不同的 columnDefinitions,所以除了 SQL Server 之外,这将失败。

所以,你必须走很长的路。这就是 Hibernate 4.3 的全部内容:

  1. 在重写的 SQLServerDialect 中注册一个新的 GUID sql 类型,并使用此方言而不是基础方言

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. 创建一个包装器 UUIDCustomType,其行为类似于内置的 UUIDCharType,但根据数据库类型进行委托(delegate)。您需要调用 init(databaseType) before 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 将选择的位置注册自定义类型(我有一个用于所有实体的公共(public)基类)。我使用 defaultForType = UUID.class 注册它,以便所有 UUID 使用它,这意味着我根本不需要注释 UUID 属性。

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

警告:实际上并没有用 postgres 进行测试,但是在 Hibernate 4.3 上对 hsqldb 和 sql server 工作得很好。

关于java - 使用 PostgreSQL 和 SQL Server hibernate UUID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42559938/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com