如何 运行 独立的 Hibernate 4 SchemaExport 与 Java Spring 配置

How to run standalone Hibernate 4 SchemaExport with Java Spring config

我们有一个 Java Spring 项目,使用 JPA 和 Hibernate 4 for ORM。我们专门使用 Java 配置,因此我们没有任何 hibernate.properties 或 persistence.xml 映射文件。

我们还使用 Spring 的 Jsr310JpaConverters 和一些实现 javax.persistence.AttributeConverter 的自定义属性转换器。包扫描会自动拾取自定义转换器。

除此之外,我们的设置还算标准,基本上就是

@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;
    }

    // ...
}

我正在寻找一种方法 运行 Hibernate 的 SchemaExport 来创建我们的数据库模式,无需 运行ning Tomcat 或 Spring 应用程序,具有相同的配置为使用 hbm2ddl=create 启动应用程序,特别是查找所有实体 类 和属性转换器。我想 运行 它与 Maven,但一旦我知道从哪里开始,我就可以弄清楚那部分。

我发现了许多针对 Hibernate 3 或 XML 配置的过时答案和库,似乎对我们的设置不起作用。我确定答案已经在那里,但在这一点上我很困惑,不知道该尝试什么。任何解决方案或指示?

我认为您需要使用 AnnotationConfiguration(): 在hibernate中,不使用hibernate.cfg.xml也可以实现数据库连接。在hibernate注解中,有一个名为AnnotationConfiguration的class。 AnnotationConfiguration 提供配置数据库属性的方法。 AnnotationConfiguration 有不同的方法,如 .addAnnotatedClass、.addProperties 等。有 .configure() 方法寻求 hibernate.cfg,如果我们不打算使用 hibernate.cfg,则不需要使用 .configure() .

假设我有实体用户

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

这是我根据 Bhushan Uniyal 的回答得出的解决方案。使用反射找到我们的实体和属性转换器。

public static void main(String... args) {
    Properties prop = new Properties();
    prop.setProperty("hibernate.connection.url", "jdbc:mysql://127.0.0.1:3306/db");
    prop.setProperty("hibernate.connection.username", "user");
    prop.setProperty("hibernate.connection.password", "xxxx");
    prop.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
    prop.setProperty("hibernate.hbm2ddl.auto", "create");

    Configuration cfg = new Configuration()
            .addPackage("com.persistence")
            .addProperties(prop);

    Reflections basePackageReflections = new Reflections(BasePackageMarker.class.getPackage().getName());

    for (Class<?> entityClass : basePackageReflections.getTypesAnnotatedWith(Entity.class)) {
        System.out.println("Adding entity class: " + entityClass.getSimpleName());
        cfg.addAnnotatedClass(entityClass);
    }

    for (Class<? extends AttributeConverter> attributeConverter : basePackageReflections.getSubTypesOf(AttributeConverter.class)) {
        System.out.println("Adding attribute converter: " + attributeConverter.getSimpleName());
        cfg.addAttributeConverter(attributeConverter);
    }

    cfg.addAttributeConverter(Jsr310JpaConverters.LocalDateConverter.class);
    cfg.addAttributeConverter(Jsr310JpaConverters.LocalDateTimeConverter.class);
    cfg.addAttributeConverter(Jsr310JpaConverters.LocalTimeConverter.class);
    cfg.addAttributeConverter(Jsr310JpaConverters.InstantConverter.class);

    new SchemaExport(cfg).create(true, true);
}