10

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

Jan Zelenka
  • 101
  • 1
  • 6

2 Answers2

2

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?

Community
  • 1
  • 1
valery.barysok
  • 604
  • 4
  • 13
2

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);
}
Timofey Gorshkov
  • 4,987
  • 6
  • 41
  • 66
  • Sorry, you say that "dialect" could be omitted, but actually I'm trying to do the same exact thing but when I'm not setting the dialect I get the error `org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set`. Do you have any suggestion on why this is happening? – Luca Sep 17 '17 at 08:21
  • Unfortunately for now I couldn't answer in which cases it works. Maybe it depends on `dataSource`... – Timofey Gorshkov Sep 19 '17 at 11:33