如何在 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 webapp 和 on 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 应用程序中问题的正确解决方案。
当然,您可以使用 对于 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的主要内容,如果未能解决你的问题,请参考以下文章