Basically I want to decide with which of 2 databases project will run.
I have following hibernateContext.xml
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:database.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.blog.przem.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
And database.properties file
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/pbdb
jdbc.user=root
jdbc.password=
What I'm trying to achieve is to add HSQLDB to my project (for development, testing) but for production I want to have MySQL DB.
I already seen some solutions:
in spring config file Can I use HSQLDB for junit testing cloning a mySQL database
in maven http://www.manydesigns.com/en/portofino/portofino3/tutorials/using-maven-profiles-and-resource-filtering
I wondering what is best approach, but I would like to keep databases settings in separate files.
Should I create database.properties2 file (with HSQL properties) and add propertyConfigurer2? And how to make dataSource bean to know which propertyConfigurer to use (I have feeling that I miss something)?
Maybe it should be done by maven?
What is professional approach to such problem (assuming that project finaly will use MySQL) - application should always use MySQL, and HSQLDB should be used only for running tests classes?
#Ralph answer works nice and as I was told it is good solution for bigger projects, and I have been given another solution how to resolve my problem so many databases can be set for project and tests files without creating additional applicationContext-db.xml ( however I don't know if having separate configuration xml's for tests is better than aproach presented below)
That code for slighty changed my hibernateContext.xml
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.blog.przem.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.connection.autocommit">false</prop>
<prop key="hibernate.transaction.flush_before_completion">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
PropertyPlaceholderConfigurer was extracted (with removed id="propertyConfigurer") to new file proprtiesContext.xml
(of course was added to hibernateContext.xml)
<beans profile="default">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:msql_database.properties</value>
</list>
</property>
</bean>
</beans>
<beans profile="testing">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:hsql_database.properties</value>
</list>
</property>
</bean>
</beans>
Then I modified and added configuration files for both databases:
msql_database.propertie
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/pbdb
jdbc.user=root
jdbc.password=
jdbc.hibernate.dialect=org.hibernate.dialect.MySQLDialect
hsql_database.propertie
jdbc.driver=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:mem;shutdown=true
jdbc.user=sa
jdbc.password=
jdbc.hibernate.dialect=org.hibernate.dialect.HSQLDialect
Now if I run (in my case Tomcat) server it using "default" - nothing special - MYSQL database is used
But if I run server with parameter
-Dspring.profiles.active="testing"
It using given profile so my project using HSQLDB HOORAY
Additionally when I add specific profile in test class (just before class name declaration):
#ActiveProfiles("default")
public class UserServiceTest {
Specified database is used for testing
So I would recommend that the server provide the database connection via JNDI.
In additon you need to define the Database Dialact. Therefore I would recommend to use a Server Parameter.
For the test cases I would use an other database configruation file, that does not use jndi, but configure the database like you need it for your tests.
For example in Tomcat: Context.xml (global or better application specific context.xml)
<Resource name="jdbc/yourApp" type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/pbdb?useUnicode=true&characterEncoding=utf8"
auth="Container"
username="" password="geheim"
maxIdle="3" maxActive="15" maxWait="10000" logAbandoned="true" removeAbandoned="true"
removeAbandonedTimeout="60" validationQuery="select 1" />
<Parameter name="yourApp.database.dialect" value="mysql" override="false" />
Spring: applicationContext-db.xml in src\main\resources
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/yourApp"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.blog.przem.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${yourApp.database.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
Now your are able to configure the application on every application server with an different database.
For Database-"integration" Tests based on Spring I would put an test specific applicationContext-db.xml without jndi and dialect property placeholder in src\test\resources (it "overrides" the normal one for the tests).
#See this answer for some additional information Spring Configuration - it describes an other way of how to name applicationContext-db.xml for the tests.
Related
I am using Spring and Hibernate in my project. My database has changed from Oracle 10g to MySQL.
Can you please tell me what changes do I need to make in my Hibernate configuration?
Also are there any changes required in my Java code.
If you are using the hibernate.cfg.xml for your project to define the database property, then you need to change it to the below values for MySQL :-
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/{db.name}</property>
<property name="hibernate.connection.username">{db.name}</property>
<property name="hibernate.connection.password">{db.password}</property>
</session-factory>
</hibernate-configuration>
Also you need to include the mysql-connector jar in your pom.xml for example
<!--Mysql-Connector-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
if you are not using the hibernate.cfg.xml and instead using some sessionFactory bean in your Spring ApplicationContext.xml. Then you need to change it to below :-
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="annotatedClasses">
</property>
<property name="hibernateProperties">
<props>
<!-- As of now not using hibernate.cfg.xml -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.validator.apply_to_ddl">false</prop>
<prop key="hibernate.validator.autoregister_listeners">false</prop>
<prop key="show_sql">true</prop>
<prop key="format_sql">true</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.pass}" />
</bean>
Please follow http://www.baeldung.com/hibernate-4-spring for complete example on how to setup hibernate with spring.
This question already has an answer here:
Rename Amazon RDS table name to capital letter throws error
(1 answer)
Closed 6 years ago.
I am migrating my windows based Spring - Hibernate application to Amazon AWS.
I am getting issues with the Database since the table names in Amazon RDS starts with uppercase letter when hibernate creates them.
eg: userlogin_permissions in Windows local Mysql changes to Userlogin_permissions.
Due to this above error , my server cannot connect to the table and is not working.
I tried using
<prop key="org.hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
but is not helping.
The following is my xml structure :
<beans profile="awsSql">
<bean class="org.apache.tomcat.jdbc.pool.DataSource" id="dataSource">
<property name="url" value="jdbc:mysql://-----------"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="#######"/>
<property name="password" value="##########"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="***-jpa"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false"/>
<property name="generateDdl" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="org.hibernate.envers.auditTablePrefix"></prop>
<prop key="org.hibernate.envers.auditTableSuffix">_AUD</prop>
<prop key="org.hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<!--<prop key="org.hibernate.ejb.naming_strategy">org.hibernate.cfg.DefaultNamingStrategy</prop>-->
<!--<prop key="hibernate.cache.provider_class">org.hibernate.cache.SingletonEhCacheProvider</prop>-->
<!--<prop key="hibernate.cache.provider_configuration">/META-INF/cache/ehcache.xml</prop>-->
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<!--<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>-->
<prop key="hibernate.generate_statistics">false</prop>
</props>
</property>
</bean>
Is there any way in which I can either make RDS use case-insensitive MYSQL , or make hibernate consistent in all OS.
I have already gone through the other related questions in here , but couldn't solve my problem.
You're looking to change the lower_case_table_names system variable and setting the value to 1.
How to change MySQL table names in Linux server to be case insensitive?
You'll have to create a new parameter group in RDS and then associate it to a mysql instance which will most likely require a restart. To see the instructions to do it via command-line that can be found below.
http://www.kulawik.de/blog/2011/02/lower_case_table_names/
I'm currently working on Java application using Spring, Hibernate, etc. under Tomcat.
I tried to configure JTA using the Atomikos but It looks like I have a problem when flush is done :(
There's a lot of configuration so I'll put the major parts:
<bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="xaDataSourceClassName">
<value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
</property>
</bean>
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" />
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.J2eeUserTransaction" />
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" depends-on="userTransactionService,atomikosTransactionManager,atomikosUserTransaction">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
<property name="allowCustomIsolationLevels" value="true"></property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jtaTransactionManager" ref="jtaTransactionManager"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">false</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
</props>
</property>
</bean>
While starting a Transaction using the #Transactional, I'm able to run queries but when saving via Hibernate getCurrentSession() I'm getting the following exception: (when commit it done)
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: The transaction was set to rollback only
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1024)
..
Caused by: com.atomikos.datasource.ResourceException: XA resource 'XADBMS': resume for XID '31302E38382E36382E32342E746D30303030313030303137:31302E38382E36382E32342E746D31' raised -5: invalid arguments
..
[11:36:30:534 (http-bio-8080-exec-3) org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorNonTrackingImpl$2.mapManagedFlushFailure(SynchronizationCallbackCoordinatorNonTrackingImpl.java:179)]
ERROR: HHH000346: Error during managed flush [XA resource 'XADBMS': resume for XID '31302E38382E36382E32342E746D30303030313030303139:31302E38382E36382E32342E746D31' raised -5: invalid arguments were given for the XA operation]
I think that i found the problem! it's related to Atomikos bug which is related to MySQL.
After adding the pinGlobalTxToPhysicalConnection=true parameter to the connection URL or as a parameter inside the com.atomikos.jdbc.AtomikosDataSourceBean Spring definition, It solved my problem.
<bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
...
<property name="xaProperties">
<props>
<prop key="pinGlobalTxToPhysicalConnection">true</prop>
</props>
</property>
</bean>
Simple DAO Layer wiht applicationContext.xml please find below my applicationContect.xml
please help me to understand why my Junit says successful but data are not inserting into the db.
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="com.VideoRental.*" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
<value>com.VideoRental.domain.Category</value>
<value>com.VideoRental.domain.Customer</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect"> org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.hbm2ddl.import_files">import.sql</prop>
<prop key="connection.autocommit">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.connection.autocommit">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
</beans>
By default, #Transactional tests will roll-back all changes when the test method completes. So even if the test passes, the changes are only valid for the current running Transaction. To persist your changes, you need to commit the transaction.
Check out the example on this SO question.
You can replace #Transactional with transactionTemplate to commit the transaction prior to finishing a test.
If you are using #Transactional annotation driven in your project, you can simply set
#TransactionConfiguration(defaultRollback = false, transactionManager = "YourTransactionManager")
in your test case will work perfectly. I've researched for days and worked good finally in my local test cases, hopefully this will helps you too.
I've been using HSQLDialect as dialect for my database (MySQL, most of tables as InnoDB) on some projects and I never had any problem with Hibernate.
I encountered MySQLSyntaxErrorException when using setMaxResults() in a project using Spring 3.1.0 and Hibernate 3.6.9, and I still wonder where does that come from..
My XML config servlet :
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:mysql://localhost:3306/product" />
<property name="username" value="root" />
<property name="password" value="***************" />
</bean>
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="mappingResources">
<list>
<value>com/social/admin/beans/DevDebugLogs.hbm.xml</value>
<value>com/social/admin/beans/Users.hbm.xml</value>
...
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect"> org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean name="/logs.html" class="com.social.admin.controllers.DebugManagerAdmin">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
I tried to switch from HSQLDialect to MySQL5InnoDBDialect and it destroyed a big part of my database, dropping entries, deleting tables .... !!!!!!! X)
Can somebody help me ?
To avoid deleting tables and data, make sure you switch Hibernate in your configuration to update:
<prop key="hibernate.hbm2ddl.auto">update</prop>
This will help you to get rid of the problems with disappearing data.
Switching to MySQL5InnoDBDialect shouldn't cause any major problems. I have been using it for a very long time in every project of mine. The only thing that might happen is the fact, that some queries might not run exactly the same under different dialects, but you will be able to examine it at runtime or during tests.