0

我们有一个使用 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 配置找到了许多过时的答案和库,似乎没有什么对我们的设置有用。我确定答案已经存在,但此时我很困惑,不知道该尝试什么。任何解决方案或指针?

4

2 回答 2

3

我认为您需要使用 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();
    }
    }
于 2017-11-09T06:44:52.017 回答
0

这是我基于 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);
}
于 2017-11-09T17:06:04.893 回答