2016-11-28 57 views
3

我使用Spring Boot 1.4.1,它包含Hibernate 5和Postgres 9.6,我試圖用UUID ID創建一個實體,但是使用Postgres的UUID而不是Hibernate。許多類似的問題都表示將列類型設置爲pg-uuid。這似乎和非數據庫生成的ID列工作,但是當我嘗試使用它的ID列,我得到有沒有辦法將Postgres的UUID生成與Hibernate的IDENTITY ID生成策略一起使用?

org.hibernate.id.IdentifierGenerationException: unrecognized id type : pg-uuid -> java.util.UUID

因此,它看起來像Hibernate正確應用類型,而不是將它轉換。

這裏是我的實體的ID列是如何設置:

@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
@org.hibernate.annotations.Type(type="pg-uuid") 
private UUID id; 

而表類似於如下設置(uuid-ossp安裝)

create table example (
    id UUID NOT NULL DEFAULT uuid_generate_v1mc(), 
    ... 
); 

我寧願有數據庫生成UUID並且不想使用Hibernate的生成策略。有沒有辦法讓這個工作?

回答

0

解決此問題的一種方法是創建一個實現ResultSetIdentifierConsumer的自定義UserType。對於一個快速和骯髒的例子,創建一個名爲PostgresIdUUIDType類,它擴展PostgresUUIDType,而實現該接口:在實體

public class PostgresIdUUIDType extends PostgresUUIDType implements ResultSetIdentifierConsumer { 

    // Naively look for a name that contains "id" in it, case insensitive 
    private static final Pattern idPattern = Pattern.compile("id", Pattern.CASE_INSENSITIVE); 

    public String getName() { 
     return "pg-id-uuid"; 
    } 

    @Override 
    public UUID consumeIdentifier(final ResultSet resultSet) throws IdentifierGenerationException { 
     try { 
      final int columnCount = resultSet.getMetaData().getColumnCount(); 
      for (int i = 1; i <= columnCount; i++) { 
       int columnType = resultSet.getMetaData().getColumnType(i); 
       // Postgres driver maps UUID to OTHER 
       if (Types.OTHER == columnType) { 
        final String name = resultSet.getMetaData().getColumnName(i); 
        if (idPattern.matcher(name).matches()) { 
         return nullSafeGet(resultSet, name, new WrapperOptions() { 
          @Override 
          public boolean useStreamForLobBinding() { 
           return false; 
          } 
          @Override 
          public LobCreator getLobCreator() { 
           return null; 
          } 
          @Override 
          public SqlTypeDescriptor remapSqlTypeDescriptor(final SqlTypeDescriptor sqlTypeDescriptor) { 
           return PostgresUUIDSqlTypeDescriptor.INSTANCE; 
          } 
         }); 
        } 
       } 
      } 
      throw new IdentifierGenerationException("Could not find id column"); 
     } catch (SQLException e) { 
      throw new IdentifierGenerationException("Error converting type", e); 
     } 
    } 
} 

然後,定義自定義類型,並用它爲你這樣的ID列:

@TypeDefs({@TypeDef(name = "pg-id-uuid", typeClass = PostgresIdUUIDType.class) }) 
@Entity 
public class Example { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @org.hibernate.annotations.Type(type="pg-id-uuid") 
    private UUID id; 

    ... 

} 

這似乎工作在我迄今爲止的有限測試。最大的問題是PostgresIdUUIDType天真地認爲UUID ID列是名稱中'id'的第一列,不區分大小寫。如果任何人有如何更好地確定哪一列實際上是ID列的想法,我會很感激的調整。

0

只需使用策略:AUTO

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private UUID id; 

這裏是worked example