设置休眠命名策略为Spring bean [英] Set hibernate naming strategy as Spring bean

查看:163
本文介绍了设置休眠命名策略为Spring bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Hibernate的spring-boot应用程序。我想提供自定义的 NamingStrategy 为每个由hibernate管理的表添加前缀。



我发现我可以使用property :

  spring.jpa.hibernate.naming_strategy = com.whatever.MyNamingStrategy 

这可以很好地工作,除非我想根据属性设置动态前缀。我的目标是拥有类似于:

  @Component 
public class PrefixNamingStrategy extends DefaultNamingStrategy {

private final字符串前缀;

@Autowired
public PrefixNamingStrategy(@Value(db.table.prefix)字符串前缀){
this.prefix = prefix;
}

@Override
public String tableName(String tableName){
return prefix + super.tableName(tableName);
}
}

显然这不适用于属性。 / p>

我试图提供自定义 SessionFactory 并提供 NamingStrategy 但没有运气 - 这个bean是在hibernate初始化后创建的,甚至似乎没有被使用:

  @Autowired 
@Bean(name =sessionFactory)
public SessionFactory getSessionFactory(DataSource dataSource){

LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);

sessionBuilder.setNamingStrategy(...); //!

return sessionBuilder.buildSessionFactory();
}

有没有办法提供自定义 NamingStrategy as bean?



干杯

解决方案

知道这是不理想的,我最终通过 VendorAdapter


  1. <命名策略委托者(注意 NamingStrategy 已被弃用):

      @Component 
    public class PrefixNamingStrategyDelegator extends ImprovedNamingStrategyDelegator {
    $ b @Autowired
    public PrefixNamingStrategyDelegator(final @Value($ {application.environment} _)字符串前缀){
    super(
    new HbmNamingStrategyDelegate(){
    @Override
    public String toPhysicalTableName(String tableName){
    return prefix + super.toPhysicalTableName(tableName);
    }
    },
    new JpaNamingStrategyDelegate(){
    @Override
    public String toPhysicalTableName(String tableName){
    返回前缀+ super.toPhysicalTableName(tableName);
    }
    }
    );
    }

    @Override
    public NamingStrategyDelegate getNamingStrategyDelegate(boolean isHbm){
    return super.getNamingStrategyDelegate(isHbm);


    $ / code $ <$ $ $ $ <$ $ $ $ $> $ J $ P $ J $>
    NamingStrategyDelegator 放入其中:

      @Component 
    / **
    *请参阅{@link org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider}
    *
    *我们不能继承这个类,但仍然需要潜入{@link org.hibernate.cfg.naming.NamingStrategyDelegator}。
    * /
    public class SpringHibernateJpaPersistenceProviderWithNamingStrategy扩展HibernatePersistenceProvider {

    private final NamingStrategyDelegator namingStrategy;

    @Autowired
    public SpringHibernateJpaPersistenceProviderWithNamingStrategy(NamingStrategyDelegator namingStrategy){
    this.namingStrategy = namingStrategy;

    $ b @Override
    public EntityManagerFactory createContainerEntityManagerFactory(final PersistenceUnitInfo info,Map properties){
    return new EntityManagerFactoryBuilderImpl(new PersistenceUnitInfoDescriptor(info),properties){
    @Override
    public Configuration buildHibernateConfiguration(ServiceRegistry serviceRegistry){
    Configuration configuration = super.buildHibernateConfiguration(serviceRegistry); $(b)如果(info instanceof SmartPersistenceUnitInfo){
    for(String managedPackage:((SmartPersistenceUnitInfo)info).getManagedPackages()){
    configuration.addPackage(managedPackage);
    }
    }

    configuration.setNamingStrategyDelegator(namingStrategy);

    返回配置;
    }
    } .build();


    code $
    $ li $ @Configuration

      @Bean 
    public AbstractJpaVendorAdapter customJPAVendorAdapter(HibernatePersistenceProvider jpaPersistenceProvider){
    返回新的HibernateJpaVendorAdapter(){
    @Override
    public PersistenceProvider getPersistenceProvider(){
    return jpaPersistenceProvider;
    }
    };




  2. PersistenceProvider 本身就是 SpringHibernateJpaPersistenceProvider 的原始副本(它的包私有并且不能被分类):

      configuration.setNamingStrategyDelegator(namingStrategy); 

    作品。但丑陋的......(你知道)


    I have a spring-boot application with Hibernate. I want to provide custom NamingStrategy to add prefix to every table managed by hibernate.

    I found I can use property:

    spring.jpa.hibernate.naming_strategy=com.whatever.MyNamingStrategy
    

    This works fine except I want to have the prefix dynamic based on properties. My goal would be to have something like:

    @Component
    public class PrefixNamingStrategy extends DefaultNamingStrategy {
    
        private final String prefix;
    
        @Autowired
        public PrefixNamingStrategy(@Value("db.table.prefix") String prefix) {
            this.prefix = prefix;
        }
    
        @Override
        public String tableName(String tableName) {
            return prefix + super.tableName(tableName);
        }
    }
    

    Obviously this doesn't work with the property.

    I tried to provide custom SessionFactoryand provide the NamingStrategy there but had no luck - the bean was created after hibernate initialized and even doesn't seem to be used:

    @Autowired
    @Bean(name = "sessionFactory")
    public SessionFactory getSessionFactory(DataSource dataSource) {
    
        LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
    
        sessionBuilder.setNamingStrategy(...); // !
    
        return sessionBuilder.buildSessionFactory();
    }
    

    Is there a way how to provide custom NamingStrategy as bean?

    Cheers

    解决方案

    Well knowing this is less than ideal I ended up going through VendorAdapter:

    1. The naming strategy delegator (note NamingStrategy has been deprecated):

      @Component
      public class PrefixNamingStrategyDelegator extends ImprovedNamingStrategyDelegator {
      
      @Autowired
      public PrefixNamingStrategyDelegator(final @Value("${application.environment}_") String prefix) {
          super(
                  new HbmNamingStrategyDelegate() {
                      @Override
                      public String toPhysicalTableName(String tableName) {
                          return prefix + super.toPhysicalTableName(tableName);
                      }
                  },
                  new JpaNamingStrategyDelegate() {
                      @Override
                      public String toPhysicalTableName(String tableName) {
                          return prefix + super.toPhysicalTableName(tableName);
                      }
                  }
          );
      }
      
      @Override
      public NamingStrategyDelegate getNamingStrategyDelegate(boolean isHbm) {
          return super.getNamingStrategyDelegate(isHbm);
      }
      }
      

    2. The JpaPersistenceProvider to sneak the NamingStrategyDelegator into it:

      @Component
      /**
       * See {@link org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider}
       *
       * We can't subclass that class but still need to sneak {@link org.hibernate.cfg.naming.NamingStrategyDelegator} into it.
       */
      public class SpringHibernateJpaPersistenceProviderWithNamingStrategy extends HibernatePersistenceProvider {
      
      private final NamingStrategyDelegator namingStrategy;
      
      @Autowired
      public SpringHibernateJpaPersistenceProviderWithNamingStrategy(NamingStrategyDelegator namingStrategy) {
          this.namingStrategy = namingStrategy;
      }
      
      @Override
      public EntityManagerFactory createContainerEntityManagerFactory(final PersistenceUnitInfo info, Map properties) {
          return new EntityManagerFactoryBuilderImpl(new PersistenceUnitInfoDescriptor(info), properties) {
              @Override
              public Configuration buildHibernateConfiguration(ServiceRegistry serviceRegistry) {
                  Configuration configuration = super.buildHibernateConfiguration(serviceRegistry);
                  if (info instanceof SmartPersistenceUnitInfo) {
                      for (String managedPackage : ((SmartPersistenceUnitInfo) info).getManagedPackages()) {
                          configuration.addPackage(managedPackage);
                      }
                  }
      
                  configuration.setNamingStrategyDelegator(namingStrategy);
      
                  return configuration;
              }
          }.build();
      }
      }
      

    3. In my @Configuration:

      @Bean
      public AbstractJpaVendorAdapter customJPAVendorAdapter(HibernatePersistenceProvider jpaPersistenceProvider) {
          return new HibernateJpaVendorAdapter() {
              @Override
              public PersistenceProvider getPersistenceProvider() {
                  return jpaPersistenceProvider;
              }
          };
      }
      

    The PersistenceProvider itself is raw copy (its package private and can't be sub classed) of SpringHibernateJpaPersistenceProvider with added line:

    configuration.setNamingStrategyDelegator(namingStrategy);
    

    Works. But ugly as ... (you know)

    这篇关于设置休眠命名策略为Spring bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆