使用 Spring Data 时,我应该如何注册自定义 Hibernate 5 数据类型 (BasicType)?

我使用Spring Data并决定要创建可在Hibernate实体中使用的新自定义数据类型。我检查了文档,并根据此官方用户指南选择并实施了它。BasicType

我希望能够在其类名下注册该类型,并能够在实体中使用新类型而无需进行注释。不幸的是,我无法引用或休眠配置来注册新类型。有没有办法在春季数据中获取它?似乎休眠的初始化对用户是隐藏的,并且不容易访问。我们使用以下类来初始化 JPA:@TypeMetadataBuilder

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactory",
        transactionManagerRef = "transactionManager",
        basePackages = {
                "..." // omitted
        }
)
public class JpaConfiguration implements TransactionManagementConfigurer {

    @Primary
    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean configureEntityManagerFactory(
        DataSource dataSource,
        SchemaPerTenantConnectionProviderImpl provider) {

        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setPersistenceUnitName("defaultPersistenceUnit");
        entityManagerFactoryBean.setDataSource(dataSource);
        entityManagerFactoryBean.setPackagesToScan(
                "..." // omitted
        );
        entityManagerFactoryBean.setJpaProperties(properties(provider));
        entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        return entityManagerFactoryBean;
    }

    @Primary
    @Bean(name = "transactionManager")
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return new JpaTransactionManager();
    }

    private Properties properties(SchemaPerTenantConnectionProviderImpl provider) {
        Properties properties = new Properties();
        // omitted
        return properties;
    }
}

我发现了很多关于如何使用Hibernate的配置对象来做到这一点的文章,但这篇文章指的是Hibernate 3和4。我还找到了如何通过Hibernate做到这一点的方法,但是当我根据我发现的文章使用它时,我会得到异常消息“org.hibernate.HibernateException:此时无法更改TypeRegistry”在Spring Data中注册自定义类型的正确方法是什么?org.hibernate.integrator.spi.Integrator


答案 1

我终于想通了。我会把它贴在这里给其他人:

我创建了一个实现接口的新类。在此类中,我可以获取对 from 元数据的引用并注册我的自定义类型。org.hibernate.boot.spi.SessionFactoryBuilderFactoryTypeResolver

package com.example.configuration;

import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderFactory;
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
import org.slf4j.LoggerFactory;

import com.example.CustomType;

public class CustomDataTypesRegistration implements SessionFactoryBuilderFactory {

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CustomDataTypesRegistration.class);

    @Override
    public SessionFactoryBuilder getSessionFactoryBuilder(final MetadataImplementor metadata, final SessionFactoryBuilderImplementor defaultBuilder) {
        logger.info("Registering custom Hibernate data types");
        metadata.getTypeResolver().registerTypeOverride(CustomType.INSTANCE);
        return defaultBuilder;
    }
}

然后,必须通过 Java ServiceLoader 机制注册该类,方法是将类的全名及其包添加到带有 name 的 java 模块目录中的文件中:org.hibernate.boot.spi.SessionFactoryBuilderFactoryMETA-INF/services

src/main/resources/META-INF/services/org.hibernate.boot.spi.SessionFactoryBuilderFactory

该文件可以包含多行,每行引用不同的类。在这种情况下,它是:

com.example.configuration.CustomDataTypesRegistration 

这样,Spring 数据将启动,并在休眠初始化期间成功注册自定义类型。

对我帮助很大的是这个SO答案,它处理Spring Data下的Hibernate 5中的模式导出。


答案 2

有一个更简单的解决方案 - 事实上,它只是1行代码。您可以只使用@TypeDef注释,从而避免注册自定义类型:

@Entity(name = "Product")
@TypeDef(
    name = "bitset",
    defaultForType = BitSet.class,
    typeClass = BitSetType.class
)
public static class Product {

    @Id
    private Integer id;

    private BitSet bitSet;

有关示例,请参阅“示例 11.使用@TypeDef注册自定义类型“在 http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html


推荐