Search code examples
javaspringhibernatejpaschemaexport

How to run standalone Hibernate 4 SchemaExport with Java Spring config


We have a Java Spring project using JPA with Hibernate 4 for ORM. We exclusively use Java config, so we don't have any hibernate.properties or persistence.xml mapping files.

We're also using Spring's Jsr310JpaConverters and some custom attribute converters implementing javax.persistence.AttributeConverter. The custom converters are picked up automatically by the package scan.

Other than that, our setup is fairly standard, basically just

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackageClasses = BasePackageMarker.class, repositoryBaseClass = InternalRepositoryImpl.class)
public class JpaConfig {

    // values loaded from property file

    public Properties jpaProperties() {
        Properties jpaProperties = new Properties();
        jpaProperties.setProperty(Environment.DIALECT, dialect);
        jpaProperties.setProperty(Environment.HBM2DDL_AUTO, getHbm2ddlAuto());
        // ...
        return jpaProperties;
    }

    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(driver);
        config.setJdbcUrl(url);
        config.setUsername(username);
        config.setPassword(password);
        // ...
        return new HikariDataSource(config);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource);
        entityManagerFactoryBean.setPackagesToScan(
                BasePackageMarker.class.getPackage().getName(),
                Jsr310JpaConverters.class.getPackage().getName()
        );
        entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManagerFactoryBean.setJpaProperties(jpaProperties());
        return entityManagerFactoryBean;
    }

    // ...
}

I'm looking for a way to run Hibernate's SchemaExport to create our database schema, without running Tomcat or the Spring application, with the same configuration as starting the application with hbm2ddl=create, specifically finding all entity classes and attribute converters. I'd like to run it with Maven, but I can figure that part out once I know where to start.

I've found many outdated answers and libraries for Hibernate 3 or for XML config, nothing seems to work for our setup. I'm sure the answer is already out there, but at this point I'm quite confused and don't know what to try. Any solutions or pointers?


Solution

  • I think what you need go with AnnotationConfiguration(): In hibernate, database connection can also be achieved without using hibernate.cfg.xml. In hibernate annotation, there is a class named as AnnotationConfiguration. AnnotationConfiguration provides the method to configure database properties. There are different methods of AnnotationConfiguration like .addAnnotatedClass, .addProperties etc. There is .configure() methods which seeks hibernate.cfg, We need not to use .configure() if we are not intended to use hibernate.cfg.

    suppose I have entity User

    package com.persistence;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Entity
    @Table(name="user")  
    public class User {
        @Id
        @GeneratedValue
        private int id;
    
        @Column(name="name")
        private String name;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    HibernateUtil class

    public class HibernateUtil {
        private static final SessionFactory concreteSessionFactory;
        static {
            try {
                Properties prop= new Properties();
                prop.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");
                prop.setProperty("hibernate.connection.username", "root");
                prop.setProperty("hibernate.connection.password", "");
                prop.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
                prop.setProperty("hbm2ddl.auto", "create");
    
                concreteSessionFactory = new AnnotationConfiguration()
               .addPackage("com.persistence")
                       .addProperties(prop)
                       .addAnnotatedClass(User.class)
                       .buildSessionFactory();
            } catch (Throwable ex) {
                throw new ExceptionInInitializerError(ex);
            }
        }
        public static Session getSession()
                throws HibernateException {
            return concreteSessionFactory.openSession();
        }
    
        public static void main(String... args){
            Session session=getSession();
            session.beginTransaction();
            User user=(User)session.get(User.class, new Integer(1));
            System.out.println(user.getName());
            session.close();
        }
        }