How should I register custom Hibernate 5 data type (BasicType) when Spring Data is used?

后端 未结 4 1270
栀梦
栀梦 2021-02-13 17:40

I use Spring Data and decided that I want to create new custom data type that can be used in Hibernate entities. I checked the documentation and choose BasicType an

相关标签:
4条回答
  • 2021-02-13 17:59

    There's a much easier solution to this -- in fact, it's just 1 line of code. You can just use the @TypeDef annotation and thus avoid having to register the custom type:

    @Entity(name = "Product")
    @TypeDef(
        name = "bitset",
        defaultForType = BitSet.class,
        typeClass = BitSetType.class
    )
    public static class Product {
    
        @Id
        private Integer id;
    
        private BitSet bitSet;
    

    For an example, see "Example 11. Using @TypeDef to register a custom Type" in http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html

    0 讨论(0)
  • 2021-02-13 18:03

    I finally figured it out. I will post it here for others:

    I created a new class that implements org.hibernate.boot.spi.SessionFactoryBuilderFactory interface. In this class I can get reference to the TypeResolver from metadata and register my custom type.

    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;
        }
    }
    

    The class must be then registered via Java ServiceLoader mechanism by adding full name of the class with its packages into the file with name org.hibernate.boot.spi.SessionFactoryBuilderFactory into the java module’s META-INF/services directory:

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

    The file can contain multiple lines, each referencing different class. In this case it is:

    com.example.configuration.CustomDataTypesRegistration 
    

    This way the Spring Data starts and custom type is successfully registered during Hibernate initialization.

    What helped my quite a lot was this SO answer that deals with schema export in Hibernate 5 under Spring Data.

    0 讨论(0)
  • 2021-02-13 18:06

    An alternative to what xMort did, can be registering a org.hibernate.boot.model.TypeContributor via ServiceLoader mechanism.

    1. Implement TypeContributor
    package com.example.configuration;
    
    import org.hibernate.boot.model.TypeContributions;
    import org.hibernate.boot.model.TypeContributor;
    import org.hibernate.service.ServiceRegistry;
    
    public class CustomTypeContributor implements TypeContributor {
        @Override
        public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
            typeContributions.contributeType(CustomType.INSTANCE);
        }
    }
    
    
    1. Create a file org.hibernate.boot.model.TypeContributor into the java module’s META-INF/services
    src/main/resources/META-INF/services/org.hibernate.boot.model.TypeContributor
    
    1. Reference the TypeContributor, file content:
    ru.eastbanctech.scs.air.transaction.repositories.StringArrayTypeContributor
    

    As of Hibernate 5.2.17, the code that picks up the TypeContributor service can be found at org.hibernate.boot.model.process.spi.MetadataBuildingProcess#handleTypes.

    0 讨论(0)
  • 2021-02-13 18:10

    I use JPA with Spring 4.3.9 and Hibernate 5.0.5 and I use custom property EntityManagerFactoryBuilderImpl.TYPE_CONTRIBUTORS with Spring LocalContainerEntityManagerFactoryBean to override Hibernate BasicTypes.

    final Properties jpaProperties = new Properties();
    jpaProperties.put(EntityManagerFactoryBuilderImpl.TYPE_CONTRIBUTORS, new TypeContributorList() {
        @Override
        public List<TypeContributor> getTypeContributors() {
             return Lists.newArrayList(new CustomDateTimeTypeContributor());
        }
    });
    final LocalContainerEntityManagerFactoryBean factoryBean = new 
    LocalContainerEntityManagerFactoryBean();
    factoryBean.setJpaProperties(jpaProperties);
    factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
    return factoryBean;
    
    0 讨论(0)
提交回复
热议问题