I want to use a UUID for the id for my domain objects. The idea is that the uuid could be provided by a client and if not a UUID will be generated. I have the definition as like so : :
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(); } }
Now assuming I strip the dashes out that are included in the java UUID or client provided UUID I'd like this to be stored in a binary field in my MySQL database. And also on retrieval have the correct format to send back.
How can I accomplish that? Thoughts on a better way to do this?
Grails and hibernate usually handle UUIDs in their string form. Using binary UUIDs is possible with a little more work. Declare id
to be of type UUID
and provide a hibernate user type to serialize it as an array of bytes. You'll also need to tell grails what SQL type to use for the UUID. For example:
class Person { static mapping = { id generator:'assigned', type: UUIDUserType, sqlType: 'varbinary(16)' } UUID id def beforeInsert = { if (!id) { id = UUID.randomUUID() } } }
The user type for UUID is:
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)) } } }