Пропуск создания определенной таблицы [Spring] [Спящий режим]

#java #spring #hibernate #spring-security #spring-jdbc

#java #весна #спящий режим #пружина-безопасность #spring-jdbc #spring-безопасность

Вопрос:

Я создаю какой-то простой проект 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?

Ответ №1:

Вам нужно сделать что-то вроде этого, чтобы исключить таблицы, которые вы не хотите создавать в базе данных.

  • Реализуйте интерфейсы 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 amp;amp; table.getName() is the table you want to exclude){
            return false;
        }
        return true;
    }

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

Ответ №2:

Если вы используете Hibernate с spring.jpa.hibernate.ddl-auto = create / create-drop, поэтому он будет пытаться создать таблицу, если она не существует, при каждом запуске, если вы используете update, она создается один раз, если не существует, и только после обновления таблицы при каждом запуске.

В качестве альтернативы попробуйте использовать прослушиватель приложений в 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 вместо общедоступного статического конечного поля, вы можете добавить поле с именем required.activation в application.properties. Она будет автоматически введена в личное поле.