跳过创建特定表格 [Spring] [Hibernate]

huangapple go评论76阅读模式
英文:

Skipping creation of a specific table [Spring] [Hibernate]

问题

我正在创建一个简单的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的值来确定是否会创建表格?

英文:

I'm creating some simple spring project (spring security) with a configuration file determining some simple values like table names etc. I defined there a boolean field REQUIRED_ACTIVATION for determining if new user have to activate his account with activation link sent for example via mail.

public static final boolean REQUIRED_ACTIVATION = true;

If I set REQUIRED_ACTIVATION value to false user is active immediately after registration. I've got defined entity which contains data for activation links:

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

When REQUIRED_ACTIVATION is set to false I'm not using this class anywhere but the table is being created in database. Is there any solution for determining if table will be created dependent on value of REQUIRED_ACTIVATION?

答案1

得分: 4

你需要像这样做一些事情,以排除你不想在数据库中创建的表格。

> - 实现 SchemaFilterProvider 和 SchemaFilter 接口
> - 在 SchemaFilter 实现中,添加一个 if 条件到 includeTable 方法,使其对于你不想创建的表格返回 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() 是你想要排除的表格){
            return false;
        }
        return true;
    }

    @Override
    public boolean includeSequence(Sequence sequence) {
        return true;
    }
}
英文:

You need to do something like this to exclude the tables you don't want to create in the database.

> - Implement the SchemaFilterProvider and the SchemaFilter interfaces
> - In the SchemaFilter implementation, add an if condition to includeTable so that it returns false for the table that you don’t
> want to create
> - Add hibernate.properties to the classpath and define hibernate.hbm2ddl.schema_filter_provider to point to the
> SchemaFilterProvider implementation

hibernate.hbm2ddl.schema_filter_provider=com.your.package.Provider

And the also:

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

得分: 0

如果您在 Spring 中使用 Hibernate,配合 spring.jpa.hibernate.ddl-auto = create / create-drop,它将在每次启动时尝试创建一个表(如果不存在的话)。如果您使用 update,它将在不存在时创建一次,然后在每次启动时只会更新表。

作为另一种方法,您可以尝试在 Spring 中使用 Application Listener:

@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 的字段,它会自动注入到私有字段中。

英文:

If you use Hibernate with spring.jpa.hibernate.ddl-auto = create / create-drop, so it would try to create a table if not exists on each startup, if you use update it create once if not exists, and after only update table on each startup.

As an alternative try to use Application Listener in 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();
    }
}

Note here is using @Value instead of public static final field, you can add the field called required.activation in application.properties. It will be automatically injected into private field.

huangapple
  • 本文由 发表于 2020年8月30日 01:01:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/63649640.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定