【问题标题】:How to run standalone Hibernate 4 SchemaExport with Java Spring config如何使用 Java Spring 配置运行独立的 Hibernate 4 SchemaExport
【发布时间】:2017-10-30 18:40:46
【问题描述】:

我们有一个使用 JPA 和 Hibernate 4 for ORM 的 Java Spring 项目。我们专门使用 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 来创建我们的数据库模式,而无需运行 Tomcat 或 Spring 应用程序,其配置与使用 hbm2ddl=create 启动应用程序的配置相同,特别是查找所有实体类和属性转换器。我想用 Maven 运行它,但是一旦我知道从哪里开始,我就可以弄清楚这部分。

我为 Hibernate 3 或 XML 配置找到了许多过时的答案和库,似乎对我们的设置没有任何作用。我确定答案已经存在,但此时我很困惑,不知道该尝试什么。有什么解决办法或者指点吗?

【问题讨论】:

  • 也许这个github.com/jpdigital/hibernate5-ddl-maven-plugin就是你要搜索的东西
  • 你可以在构建时调用一些东西——比如那个 maven 插件,或者 gradle 的东西。但是我们使用的是flyway,其他一些项目是liquibase。这是一个单独的工具/解决方案,它允许版本控制,将您的架构滚动到正确的版本 - 每次部署。
  • @AngeloImmedia 谢谢,我会看看。我们使用的是 hibernate 4,但该用户在 Github 上也有一个 hibernate4-ddl-maven-plugin,也许可以。
  • @MichałZaborowski 我们也在使用 Liquibase。事实上,我要求这个的部分原因是在不同修订/分支的模式之间创建一个 Liquibase 差异。
  • @DarioSeidl - 在这种情况下,我会在你的构建系统中创建专门的任务......

标签: java spring hibernate jpa schemaexport


【解决方案1】:

我认为您需要使用 AnnotationConfiguration(): 在hibernate中,也可以不使用hibernate.cfg.xml来实现数据库连接。在 hibernate 注解中,有一个名为 AnnotationConfiguration 的类。 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 类

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

【讨论】:

  • 谢谢,这给了我正确的想法。我只需要致电org.hibernate.cfg.Configuration.addAttributeConverter 来注册我们的转换器。
【解决方案2】:

这是我基于 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);
}

【讨论】:

    猜你喜欢
    • 2016-04-09
    • 2016-02-29
    • 1970-01-01
    • 2014-04-06
    • 1970-01-01
    • 2015-11-12
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    相关资源
    最近更新 更多