有没有办法在 spring-boot 项目中全局覆盖 UUID 二进制长度从 255 到 16?

问题描述 投票:0回答:1

我想在用于 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 类型时,如果能够避免错误和/或遗漏,那就太好了。

非常感谢!

spring-boot jpa binary mariadb uuid
1个回答
0
投票

类型描述符,将二进制实现重新映射到其他 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(引导)一起使用它并不重要。

© www.soinside.com 2019 - 2024. All rights reserved.