【问题标题】:How to set hibernate.hbm2ddl.auto on deployment in Wildfly NOT using persistence.xml如何在 Wildfly 部署时设置 hibernate.hbm2ddl.auto 不使用 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,但是没有效果。

【问题讨论】:

    标签: java hibernate jakarta-ee jpa wildfly


    【解决方案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 的意义上是不可移植的。当然,您必须使用反射编写代码......
    猜你喜欢
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    • 2016-05-25
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多