如何在 Wildfly 部署时设置 hibernate.hbm2ddl.auto 不使用 persistence.xml

Posted

技术标签:

【中文标题】如何在 Wildfly 部署时设置 hibernate.hbm2ddl.auto 不使用 persistence.xml【英文标题】:How to set hibernate.hbm2ddl.auto on deployment in Wildfly NOT using persistence.xml 【发布时间】:2015-12-22 02:29:33 【问题描述】:

我需要为使用 JPA 的 web 应用生成部署模式。 服务器是 Wildfly 9,Hibernate 作为 JPA 提供程序。

我可以通过添加来实现这一点

<property name="hibernate.hbm2ddl.auto" value="create" />

到persistence.xml。

还有其他方法可以在 Wildfly 9 中 per webappon deployment 设置此属性吗?我也试过hibernate.properties,但是没有效果。

【问题讨论】:

【参考方案1】:

没有开箱即用的 webapp 特定 部署属性。

但您可以设置您在 persistence.xml 中引用的特定于 webapp 的系统属性:

<persistence-unit >
  ...
  <properties>
    <property name="hibernate.hbm2ddl.auto" value="$mywebapp.hibernate.hbm2ddl.auto" />
  </properties>
</persistence-unit>

可以在standalone.conf(.bat) 或standalone.xml 中设置系统属性:

<server xmlns="urn:jboss:domain:3.0"> 
  <extensions> ... </extensions>
  <system-properties>
    <property name="mywebapp.hibernate.hbm2ddl.auto" value="create"/>
    ...
  </system-properties>
  ...
</server>

唯一的缺点:您必须在每个环境中设置系统属性 - 没有默认值。

另一个选项是创建一个在设置中设置值的积分器。不幸的是,配置在开始时被读入 Settings 对象,Settings.setAutoCreateSchema() 和其他 hibernate.hbm2ddl.auto 特定属性是包受保护,但您可以使用反射设置它们:

public class AutoCreateSchemaIntegrator implements Integrator 

  @Override
  public void integrate(Configuration config, SessionFactoryImplementor factory, 
            SessionFactoryServiceRegistry registry) 
    Settings settings = factory.getSettings();

    try 
      Method setter = settings.getClass().getDeclaredMethod("setAutoCreateSchema", boolean.class);
      setter.setAccessible(true);
      setter.invoke(settings, myDeploymentSpecificProperty);
     catch (ReflectiveOperationException | SecurityException e) 
      // handle exception
    
  

您需要将该集成器的全限定类名写入META-INF/services/org.hibernate.integrator.spi.Integrator

com.myproject.AutoCreateSchemaIntegrator

如果您想动态确定 hbm2ddl 设置,这是最佳选择。

【讨论】:

感谢这个出色的解决方案。选项 2 完全符合我的要求,而且效果很好。 记录:选项 2 需要依赖 org.hibernate:hibernate-core 且 scope=provided。 对于任何感兴趣的人:这里有一个小的demonstration webapp【参考方案2】:

如果您使用 Spring 和 JPA,您可以在 spring config xml 中定义所有持久性信息。因此,您可以将 hibernate.hbm2ddl.auto 包含在其中。使用 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean 作为 EntityManagerFactory 的示例 os Spring 配置文件:

  <!-- DataSource reachable by jndi,  -->
  <jee:jndi-lookup id="myDataSource" jndi-name="jdbc/XADatasource" expected-type="javax.sql.DataSource" />

  <!-- jpa Properties used later in Hibernate configuration  -->
  <util:properties id="jpaHibernateProperties">
    <prop key="hibernate.transaction.jta.platform">
      org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform
    </prop>
    <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
    <!-- validate | update | create | create-drop --> 
    <prop key="hibernate.hbm2ddl.auto">create</prop>
    <prop key="hibernate.show_sql">false</prop>
    <prop key="hibernate.format_sql">false</prop>
    <prop key="javax.persistence.transactionType">JTA</prop>
    <prop key="javax.persistence.validation.mode">AUTO</prop>
  </util:properties>

  <!-- Entity manager definition. No need of persistence.xml -->
  <bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
      </bean>
    </property>
    <property name="packagesToScan">
      <list>
        <value>com.mycompany.myproject</value>
      </list>
    </property>
    <property name="persistenceUnitName" value="myPU" />
    <property name="jtaDataSource" ref="myDataSource" />
    <!-- Hibernate specific params defined previously -->
    <property name="jpaProperties" ref="jpaHibernateProperties" />
  </bean>

【讨论】:

感谢您的回答。不幸的是,我没有在我的 webapp 中使用 Spring,所以我无法测试你的解决方案。 此解决方案不是特定于部署的,并且与仅带有 persistence.xml 的解决方案没有区别,因为给定的配置文件通常与所有部署的相同工件一起提供。尽管 Spring 可以使用第二个特定于部署的配置文件,这将是解决 Spring 应用程序中问题的正确解决方案。 当然,您可以使用 从外部属性文件中读取数据源或休眠属性【参考方案3】:

对于 wildfly,您可以使用带有默认值的 $env 表达式:

<property name="mywebapp.hibernate.hbm2ddl.auto" value="$env.DB_AUTO:validate"/>

【讨论】:

这是对@Tobias Liefke 的基于属性的解决方案的改进,但它仍然有一个缺点:它不是开箱即用的。您仍然需要通过设置系统属性来配置 wildfly。 Integrator 的解决方案对我来说效果更好,因为我可以拥有一个带有未修改 peristence.xml 的持久性 jar。然后,我可以在添加Integrator 的示例 web 应用程序中使用这个原始的持久性 jar,并且这个 web 应用程序将自动配置服务器,而无需任何先前的调整。请参阅example。 另外,这个解决方案并不是真正per webapp,因为同一个持久化 jar 可以在多个 webapps 中使用。 Integrator 解决方案的缺点是您依赖特定的持久性提供程序(即休眠),因此您的应用程序在仅依赖于 JPA 的意义上是不可移植的。当然,您必须使用反射编写代码......

以上是关于如何在 Wildfly 部署时设置 hibernate.hbm2ddl.auto 不使用 persistence.xml的主要内容,如果未能解决你的问题,请参考以下文章

Wildfly + Eclipse 部署扫描程序

带有 PostgreSQL 9.4 数据源的 WildFly 10 部署应用程序时出错

如何配置从 Eclipse 到 Wildfly 的部署

在 WildFly 上重新部署后,CDI 无法在 @Requestscoped REST 服务中将 @Singleton 设置为 @Provider

在 Wildfly/Jboss 中部署 ear 期间如何防止 HTTP 404

如何在 WildFly 10 中将爆炸战争部署为文件夹