我正在将Hibernate与Spring结合使用。作为数据库,我目前正在使用HSQL,它将数据存储在一个文件中(如SQLite)。 HSQL文件的路径目前在persistence.xml中进行了硬编码。如何在运行时访问和更改此值,以便用户可以从/向任意HSQL文件加载和保存?
的persistence.xml:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="something-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:file:~/something-db/somethingdb" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
Spring applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:data="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Database Setup -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="something-unit" />
</bean>
<data:repositories base-package="com.something.playlist"/>
<!-- Transaction Setup -->
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
</beans>
感谢任何提示!
答案 0 :(得分:3)
您可以指定JNDI数据源并将其传递给Hibernate。或者,您可以通过实现org.hibernate.connection.ConnectionProvider接口来定义自己的插件策略以获取JDBC连接
有关更多提示,请参阅:http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html
编辑2/16: StackOverflow上有一个关于创建自定义ConnectionProvider的示例:How can I set Datasource when I'm creating Hibernate SessionFactory?
如果要在运行时而不是在启动时更改数据源,则必须重新启动Hibernate会话工厂。要正确执行此操作,您必须确保在重新启动时没有正在运行的事务。以下问题/答案可以帮助您:Hibernate Sessionfactory restart | Spring
答案 1 :(得分:1)
常用的策略是在一个或多个* .properties文件中定义所有运行时配置,并使用spring的PropertyPlaceholderConfigurer加载值并在applicationContext.xml中替换占位符,在此处阅读更多内容:Best ways to deal with properties values in XML file in Spring, Maven and Eclipses。
app.properties:
# Dadabase connection settings:
hibernate.connection.driver_class=org.hsqldb.jdbcDriver
hibernate.connection.url=jdbc:hsqldb:file:~/something-db/somethingdb
hibernate.connection.username=sa
hibernate.connection.password=changeit
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hbm2ddl.auto=update
... ...
的applicationContext-dataStore.xml:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- Default location inside war file -->
<value>classpath:app.properties</value>
<!-- Environment specific location, a fixed path on deployment server -->
<value>file:///opt/my-app/conf/app.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true"/>
</bean>
... ...
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
</bean>
这里的一个问题是PropertyPlaceholderConfigurer不解析persistence.xml,解决方案是将所有hibernate配置移动到Spring的applicationContext.xml中,因为没有必要在persistence.xml中设置它们。在此处阅读更多内容:loading .properties in spring-context.xml and persistence.xml。
的persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="JPAService" transaction-type="RESOURCE_LOCAL"/>
</persistence>
的applicationContext-datSource.xml:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}"/>
<property name="url" value="${hibernate.connection.url}"/>
<property name="username" value="${hibernate.connection.username}"/>
<property name="password" value="${hibernate.connection.password}"/>
</bean>
... ...
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml"/>
<property name="persistenceUnitName" value="JPAService"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${hibernate.dialect}"/>
<property name="showSql" value="true" />
<property name="generateDdl" value="true"/>
</bean>
</property>
<property name="jpaProperties">
<!-- set extra properties here, e.g. for Hibernate: -->
<props>
<prop key="hibernate.hbm2ddl.auto">${hbm2ddl.auto}</prop>
</props>
</property>
</bean>
请注意,每次更改/opt/my-app/conf/app.properties中的配置时都需要重新启动Web应用程序,以使更改生效。
希望这有帮助。
答案 2 :(得分:1)
如果您希望通过JPA Abstraction使用hibernate,我们可以编写您的代码或服务以使用javax.persistence.EntityManagerFactory。自动连接其中一个并调用createEntityManager(Map map);您可以在地图中提供数据源。您可以使用自己的实现来包装实体管理器,该实现将参数从本地线程中拉出以创建数据源。
编辑:错误阅读上下文并看到您正在使用EntityManagerFactory。在这种情况下,只需阅读最后一部分,其中包含一个委托,该委托从threadlocal创建正确的数据源。