Change hibernate.connection.url from Spring

I use Hibernate in conjunction with Spring. As a database, I am currently using HSQL, which stores its data in a file (e.g. SQLite). The path to the HSQL file is currently hardcoded in the persistence.xml file. How can I access and change this value at runtime so that the user can load and save from / to an arbitrary HSQL file?

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> 

Thanks for any hint!

+6
source share
3 answers

You can specify a JNDI data source and pass it to Hibernate. Or you can define your own plugin strategy for receiving JDBC connections by implementing the org.hibernate.connection.ConnectionProvider interface

Additional tips: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html

Edit 2/16: There is an example of creating a custom ConnectionProvider in StackOverflow: How to set a data source when creating a Hibernate SessionFactory?

If you are going to change the data source on the fly, and not at startup, you will have to restart the Hibernate factory session. To do this correctly, you need to make sure that there are no transactions in it during the reboot. The following questions / answers will help you with this: Hibernate Sessionfactory restart | Spring

+3
source

A commonly used strategy is to define all run-time configurations in one or more * .properties files and use the spring PropertyPlaceholderConfigurer to load values ​​and replace the replacement in applicationContext.xml, in more detail here: Best ways to handle property values ​​in an XML file in Spring, Maven and eclipes .

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> 

One of the problems is that PropertyPlaceholderConfigurer does not analyze persistence.xml, the solution is to move the entire hibernate configuration to spring applicationContext.xml, since there is no need to set them in the persistence.xml file. Read more here: 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, eg for Hibernate: --> <props> <prop key="hibernate.hbm2ddl.auto">${hbm2ddl.auto}</prop> </props> </property> </bean> 

Please note that the web application needs to be restarted every time you change the configuration in / opt / my -app / conf / app.properties for the changes to take effect.

Hope this helps.

+1
source

If you want to use hibernate through JPA Abstraction, you can write your code or service to use javax.persistence.EntityManagerFactory. Autowire is one of them and call createEntityManager (Map map); You can provide a data source on the map. You can wrap an entity manager with your own implementation, which pulls a parameter from a local stream to create a data source.

EDIT: Do not read the text and see that you are using EntityManagerFactory. In this case, just read the last part where you migrate Factory with a delegate that creates the correct data source from threadlocal.

+1
source

All Articles