如何在 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的主要内容,如果未能解决你的问题,请参考以下文章
带有 PostgreSQL 9.4 数据源的 WildFly 10 部署应用程序时出错
在 WildFly 上重新部署后,CDI 无法在 @Requestscoped REST 服务中将 @Singleton 设置为 @Provider