hibernate 5 и spring — генерировать ddl с помощью SchemaExport

В настройке hibernate 4 - spring 4 можно было сгенерировать DDL с использованием объекта SchemaExport:

LocalSessionFactoryBean sfb = (LocalSessionFactoryBean) context.getBean("&sessionFactory");
SchemaExport schema = new SchemaExport(sfb.getConfiguration());  

Но hibernate 5 заменяет конструктор SchemaExport(Configuration configuration) на SchemaExport(MetadataImplementator metadataImplementator).

MetadataImplementator недоступен на

org.springframework.orm.hibernate5.LocalSessionFactoryBean or org.springframework.orm.hibernate5.LocalSessionFactoryBuilder

Я взломал это так:

MetadataSources metadataSources = (MetadataSources) FieldUtils.readField(configuration, "metadataSources", true);


Metadata metadata = metadataSources
    .getMetadataBuilder(configuration.getStandardServiceRegistryBuilder().build())
    .applyPhysicalNamingStrategy(new MyPhysicialNamingStrategy())
    .applyImplicitNamingStrategy(ImplicitNamingStrategyJpaCompliantImpl.INSTANCE)
    .build();

MetadataImplementor metadataImpl = (MetadataImplementor) metadata;
SchemaExport schema = new SchemaExport(metadataImplementor);

Но было бы неплохо иметь лучший способ, а также аннотации Validator (@NotNull, @Size) не используются для генерации DDL, и я не знаю, является ли это ошибкой в ​​​​Hibernate 5 или этой настройке.

Я использую спящий режим 5.0.0.CR4 и весну 4.2.0.RELEASE.


person Jan Zelenka    schedule 19.08.2015    source источник


Ответы (2)


Вам нужно реализовать org.hibernate.integrator.spi.Integrator, где вы можете хранить необходимые данные в каком-то держателе.

Пример работы вы можете найти здесь https://github.com/valery-barysok/spring4-hibernate5-stackoverflow-34612019


зарегистрируйте его как службу в файле META-INF/services/org.hibernate.integrator.spi.Integrator

public class Integrator implements org.hibernate.integrator.spi.Integrator {

    @Override
    public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
        HibernateInfoHolder.setMetadata(metadata);
        HibernateInfoHolder.setSessionFactory(sessionFactory);
        HibernateInfoHolder.setServiceRegistry(serviceRegistry);
    }

    @Override
    public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
    }
}

Используй это

    new SchemaExport((MetadataImplementor) HibernateInfoHolder.getMetadata()).create(true, true);
    new SchemaUpdate(HibernateInfoHolder.getServiceRegistry(), (MetadataImplementor) HibernateInfoHolder.getMetadata()).execute(true, true);

Дополнительную информацию вы можете найти здесь Programmatic SchemaExport/SchemaUpdate с Hibernate 5 и весна 4

Существует принцип Configuration over Convention для Java Persistence API, но Validation API предназначен только для проверки. Проверка не является абсолютной, вы можете поместить разные правила проверки в одно и то же поле.

если у вас например

@Size(max = 50)
@NotNull(groups = DefaultGroup.class)
@Null(groups = SecondGroup.class)
private String shortTitle;

то интерпретируется как

@Size(max = 50)
@NotNull(groups = DefaultGroup.class)
@Null(groups = SecondGroup.class)
@Column(length = 255, nullable = true)
private String shortTitle;

более подробную информацию см. здесь Почему генерация Hibernate Tools hbm2ddl не учитывает аннотации Bean Validation?

person valery.barysok    schedule 10.01.2016

Для Hibernate 5.2.7 (в моем случае) я написал метод экспорта схемы, основанный на сканировании пакетов, например:

static void exportSchema(
        DataSource dataSource,
        Class<? extends Dialect> dialect,
        String... packagesToScan) {

    StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder()
            .applySetting(DATASOURCE, dataSource)
            .applySetting(DIALECT, dialect); // dialect could be omitted
    MetadataSources metadataSources = new MetadataSources(registryBuilder.build());

    PathMatchingResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver();
    new LocalSessionFactoryBuilder(null, resourceLoader, metadataSources)
            .scanPackages(packagesToScan);

    Metadata metadata = metadataSources.buildMetadata();

    new SchemaExport()
            .setFormat(true)
            .create(EnumSet.of(STDOUT, DATABASE), metadata);
}
person Timofey Gorshkov    schedule 03.02.2017
comment
Извините, вы говорите, что диалект можно опустить, но на самом деле я пытаюсь сделать то же самое, но когда я не устанавливаю диалект, я получаю сообщение об ошибке org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set. Есть ли у вас какие-либо предложения о том, почему это происходит? - person Luca; 17.09.2017
comment
К сожалению, пока не могу ответить, в каких случаях это работает. Может быть, это зависит от dataSource... - person Timofey Gorshkov; 19.09.2017