I have several different databases for different environments to connect my application to. These are constant per installation but differ between them. In other words there is
- A dev开发者_StackOverflow中文版elopment environment which connects to a development database
- A test environment which connects to a test database and finally
- The production environment with its own database
Hibernate is used via Annotations and the code doesn't 'know' which environment it's run in. All the databases are mySQL driven but differ in url, username and password.
Currently I removed the hibernate.cfg.xml from the application and moved it to the home directory of the application-server-user but this doesn't seem like a very good solution for security reasons and because this introduced the need to manually update any changed mappings when updating an environment.
I really hope, there is a better solution but I can't find one.
You can bundle the hibernate.cfg.xml in a .jar or you could use a JPA (persistence.xml) approach instead which allows you to have different "persistence units" that you can then choose based on any variable you'd like (a properties file in your home for example). See http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/configuration.html#setup-configuration-packaging for an example of a persistence.xml.
Use placeholders for the url, user and password in the config file, and replace those placeholders with actual values when building the application (using ant, Maven, or whatever you use to build your application). The build process itself could take those values from a profile (if using Maven), or from environment variables, or from command-line arguments.
You just need to build the application three times, with different parameters : once for each target environment.
I think that the point here is not to rebuild the application 3 times. I think you can use different data sources that will define different urls of you data base server in different environment (dev/test/prod). The datasource file is an xml file that should reside externally to your artifact (ear/war or whatever you build).
So you provide always the same ear and different data source files for different environments
This is how I do it. My app-config file
<!-- Hibernate MySql SessionFactory -->
<bean id="mySqlSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="mySqlDataSource">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
.....
</props>
</property>
<property name="configLocation" value="WEB-INF/hibernate.cfg.xml"/>
</bean>
Then I have these variables defined in different properties files namely etc/dev/pejl.properties, etc/test/pejl.properties and etc/prod/pejl.properties.
Then using my ant script I build for development ...
<target name="deploydevwar" depends="build" description="Deploy application as a WAR file">
<copy overwrite="true" todir="${web.dir}/WEB-INF/classes">
<fileset dir="${etc.dir}/dev">
<include name="*.properties" />
</fileset>
</copy>
<war destfile="${name}.war"
webxml="${web.dir}/WEB-INF/web.xml">
...
</war>
<copy todir="${deploy.path}" preservelastmodified="true">
..
</copy>
<copy overwrite="true" todir="${appserver.home}">
...
</copy>
</target>
for test..
<target name="deploytestwar" depends="build" description="Deploy application as a WAR file">
<copy overwrite="true" todir="${web.dir}/WEB-INF/classes">
<fileset dir="${etc.dir}/test">
<include name="*.properties" />
</fileset>
and so on..
精彩评论