【问题标题】:Skipping creation of a specific table [Spring] [Hibernate]跳过创建特定表 [Spring] [Hibernate]
【发布时间】:2020-12-18 07:46:12
【问题描述】:

我正在创建一些简单的 spring 项目(spring security),其中的配置文件确定了一些简单的值,例如表名等。我在那里定义了一个布尔字段 REQUIRED_ACTIVATION 来确定新用户是否必须通过发送的激活链接激活他的帐户例如通过邮件。

public static final boolean REQUIRED_ACTIVATION = true;

如果我将 REQUIRED_ACTIVATION 值设置为 false,则用户在注册后立即处于活动状态。我已经定义了包含激活链接数据的实体:

@Entity
@Table(name = 'user_activation_link')
public class UserActivationLink {
   [...]
}

当 REQUIRED_ACTIVATION 设置为 false 时,我不会在任何地方使用此类,而是在数据库中创建表。是否有任何解决方案可以确定是否会根据 REQUIRED_ACTIVATION 的值创建表?

【问题讨论】:

    标签: java spring hibernate spring-security spring-jdbc


    【解决方案1】:

    您需要执行this 之类的操作来排除您不想在数据库中创建的表。

    • 实现 SchemaFilterProvider 和 SchemaFilter 接口
    • 在 SchemaFilter 实现中,向 includeTable 添加一个 if 条件,以便它为您不使用的表返回 false 想创作
    • 将 hibernate.properties 添加到类路径并定义 hibernate.hbm2ddl.schema_filter_provider 指向 SchemaFilterProvider 实现
    hibernate.hbm2ddl.schema_filter_provider=com.your.package.Provider
    

    还有:

    package com.your.package;
    
    import org.hibernate.boot.model.relational.Namespace;
    import org.hibernate.boot.model.relational.Sequence;
    import org.hibernate.mapping.Table;
    import org.hibernate.tool.schema.spi.SchemaFilter;
    import org.hibernate.tool.schema.spi.SchemaFilterProvider;
    
    public class Provider implements SchemaFilterProvider {
    
        @Override
        public SchemaFilter getCreateFilter() {
            return MySchemaFilter.INSTANCE;
        }
    
        @Override
        public SchemaFilter getDropFilter() {
            return MySchemaFilter.INSTANCE;
        }
    
        @Override
        public SchemaFilter getMigrateFilter() {
            return MySchemaFilter.INSTANCE;
        }
    
        @Override
        public SchemaFilter getValidateFilter() {
            return MySchemaFilter.INSTANCE;
        }
    }
    
    class MySchemaFilter implements SchemaFilter {
    
        public static final MySchemaFilter INSTANCE = new MySchemaFilter();
    
        @Override
        public boolean includeNamespace(Namespace namespace) {
            return true;
        }
    
        @Override
        public boolean includeTable(Table table) {
            if (//REQUIRED_ACTIVATION==true && table.getName() is the table you want to exclude){
                return false;
            }
            return true;
        }
    
        @Override
        public boolean includeSequence(Sequence sequence) {
            return true;
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果您使用带有spring.jpa.hibernate.ddl-auto = create / create-drop的Hibernate,那么它会在每次启动时尝试创建一个表如果不存在,如果您使用更新它创建一次如果不存在,并且只在每次启动时更新表。

      作为替代尝试在 Spring 中使用应用程序侦听器:

      @Value("${required.activation}")
      private Boolean isActivationRequired;
      
      @PersistenceContext   
      private EntityManager em;
      
      @EventListener
      public void handleContextRefreshEvent(ContextRefreshedEvent ctxRefreshedEvent) {
          if (!isActivationRequired) {
              em.createNativeQuery("drop table user_activation_link").executeUpdate();
          }
      }
      

      注意这里使用@Value 代替public static final 字段,您可以在application.properties 中添加名为required.activation 的字段。它会自动注入到私有字段中。

      【讨论】:

        猜你喜欢
        • 2019-02-03
        • 2020-03-25
        • 1970-01-01
        • 2016-10-29
        • 2019-03-05
        • 1970-01-01
        • 1970-01-01
        • 2017-05-29
        • 2017-08-11
        相关资源
        最近更新 更多