How to get the SQL schema generated by Hibernate/JPA in a Spring Boot Application

Spring Boot is set up with automatic schema creaation when you create a database-based application. This is very nice for prototyping but as your project develops you will want to take full control on how the database schema is setup and migrated. Unfornately it is not obvious how get a Spring Boot application to spit out the schema it is creating; here is what I ended up doing:

Put this in the test part of your main application. It will scan the components of your application and create a database schema using the defaults used by Spring Boot.

You will need to change the Environment.DIALECT (here org.hibernate.dialext.MySQL5Dialect), the output file (schema.sql) and the package “dk.christianhvid”. Leaving the package name to be an empty works but is fairly slow.

package dk.christianhvid.emu.utils;

import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import javax.persistence.Entity;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class SchemaFileDumper {
    private List findClassesWithEntityAnnotation(String packageName) throws ClassNotFoundException {
        List result = new ArrayList<>();

        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);

        provider.addIncludeFilter(new AnnotationTypeFilter(Entity.class));

        Set beanDefinitions = provider.findCandidateComponents(packageName);

        for (BeanDefinition bd : beanDefinitions) {
            result.add(Class.forName(bd.getBeanClassName()));
        }

        return result;
    }

    public void dumpSchema() throws ClassNotFoundException {
        Configuration configuration = new Configuration();

        configuration.setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");

        for (Class klass : findClassesWithEntityAnnotation("dk.christianhvid")) {
            configuration.addAnnotatedClass(klass);
        }

        configuration.setNamingStrategy(new SpringNamingStrategy());

        SchemaExport schema = new SchemaExport(configuration);
        schema.setOutputFile("schema.sql");
        schema.create(false, false);
    }

    public static void main(String[] args) throws ClassNotFoundException {
        new SchemaFileDumper().dumpSchema();
    }
}