Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hibernate 5 and spring - generate ddl using SchemaExport

In hibernate 4 - spring 4 setup it was possible to generate DDL using SchemaExport object:

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

But hibernate 5 replaces SchemaExport(Configuration configuration) constructor with SchemaExport(MetadataImplementator metadataImplementator).

MetadataImplementator is not readily available on

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

I hacked it like this:

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);

But it would be nice to have a better way and also, Validator annotations (@NotNull, @Size) are not used for DDL generation and I don't know if it is a bug in Hibernate 5 or this setup.

I am using hibernate 5.0.0.CR4 and spring 4.2.0.RELEASE

like image 587
Jan Zelenka Avatar asked Aug 19 '15 08:08

Jan Zelenka


2 Answers

You need to implement org.hibernate.integrator.spi.Integrator where you can store required data to some holder.

Work example you can find here https://github.com/valery-barysok/spring4-hibernate5-stackoverflow-34612019


register it as the service at META-INF/services/org.hibernate.integrator.spi.Integrator file

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) {
    }
}

Use it

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

Additional info you can find here Programmatic SchemaExport / SchemaUpdate with Hibernate 5 and Spring 4

There is Configuration over Convention principle for Java Persistence API but Validation API is intended for validation purpose only. Validation is not absolute you can put different validation rules on the same field.

if you have for example

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

then it is interpreted as

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

see more details here Why does Hibernate Tools hbm2ddl generation not take into account Bean Validation annotations?

like image 85
valery.barysok Avatar answered Nov 10 '22 20:11

valery.barysok


For Hibernate 5.2.7 (in my case) I've wrote a method to export schema that is based on packages scan like:

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);
}
like image 39
Timofey Gorshkov Avatar answered Nov 10 '22 21:11

Timofey Gorshkov