【问题标题】:Set hibernate naming strategy as Spring bean将休眠命名策略设置为 Spring bean
【发布时间】:2015-08-05 10:06:21
【问题描述】:

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

我发现我可以使用属性:

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

这很好用,除了我想根据属性动态地添加前缀。我的目标是:

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

显然这不适用于该属性。

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

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

    LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);

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

    return sessionBuilder.buildSessionFactory();
}

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

干杯

【问题讨论】:

    标签: spring hibernate spring-boot


    【解决方案1】:

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

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

      @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. JpaPersistenceProviderNamingStrategyDelegator 偷偷溜进去:

      @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. 在我的@Configuration

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

    PersistenceProvider 本身是 SpringHibernateJpaPersistenceProvider 的原始副本(它的包是私有的,不能被子分类),并添加了一行:

    configuration.setNamingStrategyDelegator(namingStrategy);
    

    有效。但丑得像...(你知道)

    【讨论】:

      猜你喜欢
      • 2020-01-30
      • 2014-05-03
      • 1970-01-01
      • 2011-05-01
      • 2010-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多