2011-02-26 21 views
8

Etki alanı nesnelerimin kimliği için UUID kullanmak istiyorum. Fikir, uuid'in bir istemci tarafından sağlanabilmesi ve bir UUID üretilmemesi ise. Öyle gibi tanımı var:grauları id olarak tanımladı ve ikili sütuna eşleme

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(); 
      } 
} 

Şimdi bu benim MySQL veritabanında bir ikili alanda depolanacak istiyorum ben UUID sağlanan java UUID veya müşteri dahildir dışarı tire şerit varsayarak . Ve ayrıca geri alma, geri göndermek için doğru biçime sahip.

Bunu nasıl yapabilirim? Bunu daha iyi bir şekilde düşünmek?

cevap

3

Taneler ve hazırda bekletme genellikle UUID'leri dize biçiminde işler. İkili UUID kullanımı biraz daha fazla çalışma ile mümkündür. UUID türünde olmak üzere id numaralı bildirimi bildirin ve bayt dizisi olarak serileştirilmesi için hazırda bekleme kullanıcı türü sağlayın. Ayrıca, UUID için hangi SQL türünün kullanılacağını da bilmeniz gerekir. Örneğin:

class Person { 
    static mapping = { 
     id generator:'assigned', type: UUIDUserType, sqlType: 'varbinary(16)' 
    } 

    UUID id 

    def beforeInsert = { 
     if (!id) { 
      id = UUID.randomUUID() 
     } 
    } 
} 

UUID'sine kullanıcı tipi: MySQL doesnt

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)) 
     } 
    } 
} 
+0

: 2011-02-27 10: 18: 33.818 [ana] HATA hbm2ddl.SchemaExport - Başarısız: oluşturmak tablo kişi (id tinyblob değil null, sürüm bigint değil null, birincil anahtar (id)) 2011-02-27 10: 18: 33,819 [ana] ERROR hbm2ddl.SchemaExport - BLOB/METİN sütun 'id' olmadan anahtar özellikleri kullanılır bir anahtar uzunluğu 2011-02-27 10: 18: 36,702 [main] ERROR util.JDBCExceptionReporter - Tablo 'testuuid.person' mevcut değil – imrank1

+0

Hata! Grails'in String olmayan UUID'leri otomatik olarak ele aldığını varsaydım, ancak çıkmadı. Cevabı bir düzeltme ile güncelledim. – ataylor

+0

ahh evet özel bir kullanıcı tipi. Mezar ya da hazırda beklemenin bizim için bununla ilgileneceğini düşünürdüm. Genel olarak çözüm işe yarıyor.Kapı/hazırda bekletme, varlıklar için birincil anahtar olarak varbinary (16) kullanırken aittir. Tek çözüm, ilk önce veritabanı şemasını oluşturmak gibi görünüyor. – imrank1