解决此问题的一种方法是创建实现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列,我会很感激.