我想在用于 spring-boot 项目的 MariaDB 数据库中使用二进制 UUID,而不是使用 varchar uuid。现在,我可以通过将列长度覆盖为 16 来创建、保存和搜索二进制 UUID,但我必须手动将注释
@Column(length=16)
放在任何 UUID 字段上。
有没有办法在项目中全局进行此修改? 换句话说,有没有一种方法,对于项目中的所有 UUID 字段,jpa/hibernate 创建一个列“binary(16)”而不是“binary(255)”?
我的问题是,默认情况下,UUID 会转换为二进制 (255) 到 MariaDB,并且使用此配置,JPA 存储库查询在搜索 UUID 字段时无法找到任何数据。
要实现 Jpa 存储库查询,我必须在任何 UUID 字段上添加
@Column(length=16)
。
我尝试使用“@Converter”,但 Convert 注释不应用于指定以下内容的转换:Id 属性、版本属性、关系属性等...并且它不适用于 uuid 关系字段。
我还尝试使用我自己的自定义休眠类型(此处示例:https://www.maxenglander.com/2017/09/01/optimized-uuid-with-hibernate.html)但jpa存储库查询不没找到任何东西。
现在我有这个: 我的抽象实体:
public abstract class GenericEntity {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Column(length = 16)
private UUID id;
//...
}
在另一个对象中使用 uuid 时:
public abstract class AnotherEntity extends GenericEntity {
@NotNull
@Column(length = 16)
private UUID owner;
//...
}
我正在寻找一种方法来覆盖 UUID 字段生成,而无需将“@Column(length = 16)”到处放置。
在其他功能中使用 UUID 类型时,如果能够避免错误和/或遗漏,那就太好了。
非常感谢!
类型描述符,将二进制实现重新映射到其他 Hibernate typedef:
import java.sql.Types;
import java.util.UUID;
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
import org.hibernate.type.descriptor.sql.BinaryTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
public class MariaDBUuidTypeDescriptor extends BinaryTypeDescriptor {
private static final long serialVersionUID = 1L;
public static final MariaDBUuidTypeDescriptor INSTANCE = new MariaDBUuidTypeDescriptor();
public MariaDBUuidTypeDescriptor() {
super();
}
@Override
public int getSqlType() {
return Types.OTHER;
}
@Override
@SuppressWarnings("unchecked")
public BasicJavaDescriptor<UUID> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
return (BasicJavaDescriptor<UUID>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( UUID.class );
}
}
类型本身,包装上面的描述符并将其绑定到 UUID classdef。
import java.util.UUID;
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
import org.hibernate.type.descriptor.java.UUIDTypeDescriptor;
public class MariaDBUuidType extends AbstractSingleColumnStandardBasicType<UUID> {
private static final long serialVersionUID = 1L;
public static final MariaDBUuidType INSTANCE = new MariaDBUuidType();
public MariaDBUuidType() {
super( MariaDBUuidTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE );
}
@Override
public String getName() {
return "mariadb-uuid-binary";
}
@Override
protected boolean registerUnderJavaType() {
return true;
}
}
修改后的 Hibernate 方言,利用类型并将其所有出现的地方重新映射到
binary(16)
import java.sql.Types;
import org.hibernate.HibernateException;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.MariaDB103Dialect;
import org.hibernate.service.ServiceRegistry;
public class MariaDB103UuidAwareDialect extends MariaDB103Dialect {
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
registerColumnType( Types.OTHER, "uuid" );
typeContributions.contributeType( MariaDBUuidType.INSTANCE );
}
@Override
public String getTypeName(int code, long length, int precision, int scale) throws HibernateException {
String typeName = super.getTypeName(code, length, precision, scale);
if (Types.OTHER == code && "uuid".equals(typeName)) {
return "binary(16)";
} else {
return typeName;
}
}
}
请注意,这是仅 Hibernate 的实现,即是否与 Spring(引导)一起使用它并不重要。