grails 使用 uuid 作为 id 并映射到二进制列
Posted
技术标签:
【中文标题】grails 使用 uuid 作为 id 并映射到二进制列【英文标题】:grails using uuid as id and mapping to to binary column 【发布时间】:2011-07-04 23:51:51 【问题描述】:我想为我的域对象使用 UUID 作为 id。这个想法是 uuid 可以由客户端提供,如果不是,将生成 UUID。我有这样的定义::
class Person
static mapping =
id generator:'assigned'
String id
def getUUID =
return java.util.UUID.randomUUID().toString();
transient beforeInsert =
if ( id == null || id.equals(""))
id = getUUID();
现在假设我去掉了包含在 java UUID 或客户端提供的 UUID 中的破折号,我希望将其存储在我的 mysql 数据库中的二进制字段中。并且在检索时也有正确的格式发回。
我怎样才能做到这一点?想到更好的方法来做到这一点?
【问题讨论】:
【参考方案1】:Grails 和 hibernate 通常以字符串形式处理 UUID。使用二进制 UUID 需要做更多的工作。将id
声明为UUID
类型并提供休眠用户类型以将其序列化为字节数组。您还需要告诉 grails 用于 UUID 的 SQL 类型。例如:
class Person
static mapping =
id generator:'assigned', type: UUIDUserType, sqlType: 'varbinary(16)'
UUID id
def beforeInsert =
if (!id)
id = UUID.randomUUID()
UUID 的用户类型是:
import java.nio.ByteBuffer
import java.nio.LongBuffer
import java.sql.ResultSet
import java.sql.PreparedStatement
import java.sql.Types
import org.hibernate.usertype.UserType
public class UUIDUserType implements UserType
int[] sqlTypes() [Types.VARBINARY] as int []
Class returnedClass() UUID
Object nullSafeGet(ResultSet resultSet, String[] names, owner)
byte[] value = resultSet.getBytes(names[0])
return value ? bytesToUuid(value) : null
void nullSafeSet(PreparedStatement statement, value, int index)
if (value == null)
statement.setNull(index, Types.VARBINARY)
else
statement.setBytes(index, uuidToBytes(value))
boolean equals(x, y) x == y
int hashCode(x) x.hashCode()
Object deepCopy(value) value
boolean isMutable() false
Serializable disassemble(value) value
Object assemble(Serializable cached, owner) cached
def replace(original, target, owner) original
static byte[] uuidToBytes(uuid)
def bytes = new byte[16];
ByteBuffer.wrap(bytes).asLongBuffer().with
put(0, uuid.mostSignificantBits)
put(1, uuid.leastSignificantBits)
bytes
static UUID bytesToUuid(bytes)
ByteBuffer.wrap(bytes).asLongBuffer().with
new UUID(get(0), get(1))
【讨论】:
这在 MySQL 上不起作用:2011-02-27 10:18:33,818 [main] 错误 hbm2ddl.SchemaExport - 不成功:创建表人(id tinyblob 不为空,版本 bigint 不为空,主键(id)) 2011-02-27 10:18:33,819 [main] 错误 hbm2ddl.SchemaExport - BLOB/TEXT 列“id”在没有密钥长度的密钥规范中使用 2011-02-27 10:18:36,702 [main]错误 util.JDBCExceptionReporter - 表 'testuuid.person' 不存在 哎呀,你是对的。我假设 grails 会自动处理非字符串 UUID,但事实证明并非如此。我已经通过修复更新了答案。 啊是的自定义用户类型。我原以为 grails 或 hibernate 会为我们解决这个问题。总体而言,该解决方案有效..但是当使用 varbinary(16) 作为实体的主键时,grails/hibernate 的 belongsTo 关系存在问题。唯一的解决方案似乎是先手动创建数据库方案。以上是关于grails 使用 uuid 作为 id 并映射到二进制列的主要内容,如果未能解决你的问题,请参考以下文章