从Spring中更改hibernate.connection.url

时间:2013-02-13 16:49:41

标签: spring hibernate hsqldb

我正在将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>

感谢任何提示!

3 个答案:

答案 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创建正确的数据源。