#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. Она будет автоматически введена в личное поле.