Hibernate, PostgreSQL : Write to 2 different databases on different servers. - java

I am working on a Spring-MVC application which we have running on 2 servers, one is our testing server, 2nd one is our live server. Is there any way that I can configure Hibernate to write any and all DB related queries on both servers. Example : User A saved Object A on live server, then write the same object on Test-server, vice-versa is not required. Our test and live server both have same setting and same database. Thank you.
root-context.xml :
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property name="driverClassName" value="org.postgresql.Driver"/>
<beans:property name="url"
value="jdbc:postgresql://localhost:PORT/DB_NAME"/>
<beans:property name="username" value="USERNAME"/>
<beans:property name="password" value="PASSWORD"/>
<beans:property name="removeAbandoned" value="true"/>
<beans:property name="removeAbandonedTimeout" value="20"/>
<beans:property name="defaultAutoCommit" value="false"/>
</beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="packagesToScan" value="com.tooltank.spring.model"/>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<!-- <beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>-->
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
<beans:prop key="cache.use_second_level_cache">true</beans:prop>
<beans:prop key="cache.use_query_cache">true</beans:prop>
<beans:prop key="hibernate.order_updates">true</beans:prop>
<beans:prop key="show_sql">false</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<hibernate.version>4.3.9.Final</hibernate.version>
If anymore data is required, please let me know. Thank you.

Not in any way that you're probably hoping for. They have completely different transactional contexts, so you can't just pretend that 2 databases are one.
What if one database throws an exception and the other one doesn't? Did the tx commit or roll back? Hibernate certainly doesn't expect it to be "half success".
You could make the test server a slave of the live server and just write to the live server. This is not a simple solution either and can be outright stupid.

Related

Spring, Maven : Maven tests failing with 2 transaction managers

I have written a few test cases for our Spring-MVC based project. As the project is huge, we are using 2 Data-sources and 2 Transaction managers, both talking to the same Database using HikariPool.
When using the webapp, if I save an object with 1st data source and retrieve it with 2nd data source, it's working fine, but not when I am running mvn test.
Any ideas?
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml",
"file:src/main/webapp/WEB-INF/spring/root-context.xml", "file:src/main/webapp/WEB-INF/spring/appServlet/security-applicationContext.xml"})
#Ignore
#WebAppConfiguration
#Transactional
public class TestingController {
//All autowired dependencies
}
DAO layer where code is failing :
#Repository
#Transactional
public class GroupNotesDAOImpl implements GroupNotesDAO {
#Autowired
#Qualifier(value = "sessionFactory_origin")
private final SessionFactory sessionFactory;
#Autowired
#Qualifier(value = "sessionFactory_extended")
private final SessionFactory sessionFactory_extended;
#Override
public GroupNotes getGroupNoteByIdExtended(int id){
Session session = this.sessionFactory_extended.getCurrentSession();
System.out.println("Id of note is "+id);
// Getting null below, even though the object exists, id is non-zero
return (GroupNotes) session.get(GroupNotes.class, id);
}
}
Inside a browser, everything is working just fine. The extended data source is for long running services.
Save DAO code :
#Override
public int saveGroupNoteAndReturnId(GroupNotes mnotes, int msectionid) {
Session session = this.sessionFactory.getCurrentSession();
if(mnotes.getCanvasId()!=0) {
GroupSection groupSection = (GroupSection) session.get(GroupSection.class, msectionid);
groupSection.getSectionsnotes().add(mnotes);
mnotes.setOwnednotes(groupSection);
int saveId = (Integer) session.save(mnotes);
session.flush();
return saveId;
}else {
return 0;
}
}
Test cases :
// First test calls the save method
groupNotes = TestUtils.createGroupNotes("testtag", "testtext", loggedInUser.getId());
groupNotes.setCanvasId(mcanvasId);
int noteId = this.groupNotesService.saveGroupNoteAndReturnId(groupNotes, msectionId);
assert noteId!=0;
The 2nd test calls to retrieve the object for duplicating. As duplication is a long run process, it's executed with extended transaction manager
int success =this.groupNotesService.duplicateGroupNote(noteId, msectionId, groupId, true,true,4.0,false);
assert(success!=0);
root-context.xml :
<beans:bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<beans:property name="dataSourceClassName" value="org.USERNAMEql.ds.PGSimpleDataSource"/>
<beans:property name="maxLifetime" value="30000" />
<beans:property name="idleTimeout" value="40000" />
<beans:property name="connectionTimeout" value="60000"/>
<beans:property name="maximumPoolSize" value="6"/>
<beans:property name="dataSourceProperties">
<beans:props>
<beans:prop key="url">jdbc:USERNAMEql://localhost:PORT_NUMBER/DB_NAME</beans:prop>
<beans:prop key="user">USERNAME</beans:prop>
<beans:prop key="password">PASSWORD</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory_origin"/>
</beans:bean>
<beans:bean id="sessionFactory_origin" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="packagesToScan" value="com.ourapp.spring.model"/>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.jdbc.lob.non_contextual_creation">true</beans:prop>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.USERNAMEQL9Dialect</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<beans:prop key="hibernate.jdbc.batch_size">50</beans:prop>
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
<beans:prop key="cache.use_second_level_cache">true</beans:prop>
<beans:prop key="cache.use_query_cache">true</beans:prop>
<beans:prop key="hibernate.order_updates">true</beans:prop>
<beans:prop key="show_sql">false</beans:prop>
<beans:prop key="connection.release_mode">after_statement</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="extended_transactions_data_source" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<beans:property name="dataSourceClassName" value="org.USERNAMEql.ds.PGSimpleDataSource"/>
<beans:property name="maximumPoolSize" value="3" />
<beans:property name="maxLifetime" value="30000" />
<beans:property name="idleTimeout" value="40000" />
<beans:property name="connectionTimeout" value="60000"/>
<beans:property name="dataSourceProperties">
<beans:props>
<beans:prop key="url">jdbc:USERNAMEql://localhost:PORT_NUMBER/DB_NAME</beans:prop>
<beans:prop key="user">USERNAME</beans:prop>
<beans:prop key="password">PASSWORD</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<tx:annotation-driven transaction-manager="transactionManager_extended"/>
<beans:bean id="transactionManager_extended" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory_extended"/>
</beans:bean>
<beans:bean id="sessionFactory_extended" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="extended_transactions_data_source" />
<beans:property name="packagesToScan" value="com.ourapp.spring.model"/>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.jdbc.lob.non_contextual_creation">true</beans:prop>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.USERNAMEQL9Dialect</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<beans:prop key="hibernate.jdbc.batch_size">25</beans:prop>
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
<beans:prop key="cache.use_second_level_cache">false</beans:prop>
<beans:prop key="cache.use_query_cache">false</beans:prop>
<beans:prop key="hibernate.order_updates">true</beans:prop>
<beans:prop key="show_sql">false</beans:prop>
<beans:prop key="connection.release_mode">after_statement</beans:prop>
</beans:props>
</beans:property>
</beans:bean>

Hibernate : C3p0 pool configuration slowing down entire server.

I am working on a Spring-MVC application in which we are using Hibernate and c3p0 for Database transactions and connection pooling. Most of the time it works really good, no issues. But in certain situations I have to copy a lot of objects and files in the current transaction. When that happens, the entire server slows down and finally I start getting could not rollback exception . Anything wrong with my c3p0 settings? Thank you.
pom.xml :
<!--- Hibernate dependencies -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.3.9.Final</version>
</dependency>
root-context.xml :
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property name="driverClassName" value="org.postgresql.Driver"/>
<beans:property name="url"
value="jdbc:postgresql://localhost:PORT/DB_NAME"/>
<beans:property name="username" value="USERNAME"/>
<beans:property name="password" value="PASSWORD"/>
<beans:property name="removeAbandoned" value="true"/>
<beans:property name="removeAbandonedTimeout" value="20"/>
<beans:property name="defaultAutoCommit" value="false"/>
</beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="packagesToScan" value="com.ourapp.spring.model"/>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<!--<beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>-->
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
<beans:prop key="cache.use_second_level_cache">true</beans:prop>
<beans:prop key="cache.use_query_cache">true</beans:prop>
<beans:prop key="hibernate.order_updates">true</beans:prop>
<beans:prop key="show_sql">false</beans:prop>
<beans:prop key="hibernate.c3p0.min_size">1</beans:prop>
<beans:prop key="hibernate.c3p0.max_size">750</beans:prop>
<beans:prop key="hibernate.c3p0.acquire_increment">1</beans:prop>
<beans:prop key="hibernate.c3p0.idle_test_period">1000</beans:prop>
<beans:prop key="hibernate.c3p0.max_statements">150</beans:prop>
<beans:prop key="hibernate.c3p0.timeout">1200</beans:prop>
<beans:prop key="hibernate.connection.release_mode">auto</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
Thank you.
For starters you aren't using C3P0 simply because you have configured the org.apache.commons.dbcp.BasicDataSource as a DataSource and are injecting that into your LocalSessionFactoryBean. This basically renders all the hibernate.c3p0 settings useless as they will be ignored.
Next you have issues with processing large amounts of data and I highly doubt the issue is your DataSource or connection pool but rather the way you are processing your entities and how you have configured Hibernate.
To speedup batch processing you want to flush every x records to the database and clear the first level cache. Why do you want to do this you might wonder. It has all to do with how Hibernate works, when you persist an entity what Hibernate does it will add it to the first level cache (the Session or EntityManager in case of JPA). Each time you add an item to the first level cache it will do a dirty check on ALL of the entities in the first level cache to determine if something needs to be flushed. Now this will be fast for the first few entities but will become increasingly slower and slower.
Lets configure and code things for a batch size of 50.
First you want to configure hibernate to have a proper batch size and you want to order the insert and update statements. If you do this you can benefit from the fact that JDBC can now do a Batch Update (i.e. one insert or update statement to modify 50 records instead of 50 single insert/update statement).
Hibernate Configuration
<beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="packagesToScan" value="com.ourapp.spring.model"/>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<!--<beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>-->
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
<beans:prop key="hibernate.cache.use_second_level_cache">true</beans:prop>
<beans:prop key="hibernate.cache.use_query_cache">true</beans:prop>
<beans:prop key="hibernate.jdbc.batch_size">50</beans:prop>
<beans:prop key="hibernate.order_inserts">true</beans:prop>
<beans:prop key="hibernate.order_updates">true</beans:prop>
<!-- If you use versioned entities set this to true as well -->
<beans:prop key="hibernate.jdbc.batch_versioned_data">true<beans:prop>
</beans:props>
</beans:property>
</beans:bean>
Code Modification
public void yourLargeDataSetProcessingMethod() {
Session session = sessionFactory.getCurrentSession();
int i = 0;
for (YourItem item : List<YourItem> items) {
i++:
// Here will be processing / creation
if (i % 50 == 0) {
session.flush();
session.clear();
}
}
session.flush();
session.clear();
}
This will probably speed up your processing and database locking.
A final note, instead of Commons DBCP or C3P0 I would suggest to use HikariCP as the connection pool. It is very small and very fast and actively maintained (whereas C3P0 has been dormant for quite some time already).
Here is a nice resource (with benchmarks etc.) on what each setting does and add or removes performance wise and how to configure things properly.

dificullty while using two databases in the spring hibernate application

I am trying to use 2 databases in my spring project. It is working fine if I use 1 database but when add other databases I am getting following error message.
org.hibernate.HibernateException: No Session found for current thread
dispatcher-servlet
<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="sample" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.kendoui.spring.models.Constraint</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
<beans:prop key="hibernate.format_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory" />
</beans:bean>
<beans:bean id="Ascent" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<beans:property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<beans:property name="url" value="jdbc:sqlserver://localhost:1433;databaseName=Ascent;" />
<beans:property name="username" value="sa" />
<beans:property name="password" value="abc123" />
<beans:property name="maxActive" value="1" />
<beans:property name="maxIdle" value="1" />
</beans:bean>
<beans:bean id="sessionFactory2" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="Ascent" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.kendoui.spring.models.ItemOperationSequence</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
<beans:prop key="hibernate.format_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="transactionManager2" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory2" />
</beans:bean>
<!-- Enable annotation driven transactions. Required by getCurrentSession(). -->
<tx:annotation-driven/>
DAO implemantation
#Transactional("transactionManager2")
#Component
public class ItemOprSeqDaoImpl implements ItemOprSeqDao {
#Autowired
private SessionFactory sessionFactory;
#Override
public List<ItemOperationSequence> getList(String Itemcode) {
Session session = sessionFactory.getCurrentSession();
String queryStr= "select * from [#is_itemtrvoprdetails]";
Query query= session.createSQLQuery(queryStr).addEntity(ItemOperationSequence.class);
List <ItemOperationSequence> d=query.list();
return d;
}
}
I tried many different things but it is not working.
I tried using <beans:qualifier value="Ascent" /> in my servlet
and
#Qualifier(value="SessionFactory2") in my DAO
but nothing seems to work.
Anyone knows the answer to this problem. I would really appreciate if you could help.
Thanks in advance.
<tx:annotation-driven/> should be declared twice once for each transaction manager.
<tx:annotation-driven transaction-manager="transactionManager2"/>
and
<tx:annotation-driven transaction-manager="transactionManager"/>
Also add #Qualifier for
#Autowired
#Qualifier(value="SessionFactory2")
private SessionFactory sessionFactory;
You need to define a ChainedTransactionManager with both HibernateTransactionManagers as input.
I am not used to spring xml configuration, but it should look like this.
Than just use only #Transactional without a value.
<beans:bean id="transactionManager1" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory" />
</beans:bean>
<beans:bean id="transactionManager2" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory2" />
</beans:bean>
<beans:bean id="transactionManager" class="org.springframework.data.transaction.ChainedTransactionManager">
<beans:constructor-arg>
<list>
<beans:ref bean="transactionManager1" />
<beans:ref bean="transactionManager2" />
</list>
</beans:constructor-arg>
</beans:bean>
Okay I solved the problem by doing this.
first declared transaction-manager
<tx:annotation-driven transaction-manager="transactionManager1"/>
Then in my DAO used
#Transactional("transactionManager2")
#Component
public class ItemOprSeqDaoImpl implements ItemOprSeqDao {
#Autowired
#Qualifier("sessionFactory2")
private SessionFactory sessionFactory;
//then rest of the code
}
Its working fine now. Thanks you guys for your help.

Spring MVC : Tying session attributes to each browser tab

I am working on Spring-MVC application in which I am setting and
getting some session attributes which I need in backend. The problem
is, Spring or the browser, someone out of the both is tying these
session attributes to different browsers rather than different tabs.
So if I open a new tab in the same browser, then it is updating the
session attribute for both tabs.
How can I remedy this problem? I tried using session to scope, request, etc. But nothing works. here is my controller and servlet-context.xml
Controller :
#Controller
#Scope("request")
public class PersonController {
#Secured("ROLE_USER")
#RequestMapping(value = "/loadsection/{id}")
public String loadNotePage(#PathVariable("id") Integer id, HttpSession session) {
// here i am setting the canvasid, which I would like to access in other methods
session.setAttribute("canvasid",id);
if (this.personService.returnCurrentOperationalMode()) {
session.setAttribute("canvasid",id);
return "redirect:/section/listing";
} else {
GroupCanvas mcanvas = this.groupCanvasService.getCanvasById(id);
this.personService.setCurrentCanvas(mcanvas.getMcanvasid());
return "redirect:/section/listing";
}
}
#Secured("ROLE_USER")
#RequestMapping(value = "/addbatchsections", method = RequestMethod.POST)
public #ResponseBody String addBatchSections(HttpSession session, #RequestBody Section[] sections) {
int canvasid = (Integer) session.getAttribute("canvasid");
try {
List<Section> sectionList = new ArrayList<>();
for (Section section : sections) {
sectionList.add(section);
}
this.sectionService.addBatchSections(sectionList,canvasid);
return "success";
} catch (Exception e) {
return "failure";
}
}
Servlet-Context.xml
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<resources mapping="/resources/" location="/resources/" />
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property name="driverClassName" value="org.postgresql.Driver" />
<beans:property name="url"
value="jdbc:postgresql://localhost:5432/Person2"/>
<beans:property name="username" value="postgres" />
<beans:property name="password" value="asayhk2787" />
<beans:property name="removeAbandoned" value="true"/>
<beans:property name="removeAbandonedTimeout" value="20"/>
<beans:property name="defaultAutoCommit" value="false"/>
</beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.journaldev.spring.model.Person</beans:value>
<beans:value>com.journaldev.spring.model.Notes</beans:value>
<beans:value>com.journaldev.spring.model.Canvas</beans:value>
<beans:value>com.journaldev.spring.model.Section</beans:value>
<beans:value>com.journaldev.spring.model.Attachment</beans:value>
<beans:value>com.journaldev.spring.model.GroupAccount</beans:value>
<beans:value>com.journaldev.spring.model.GroupMembers</beans:value>
<beans:value>com.journaldev.spring.model.GroupCanvas</beans:value>
<beans:value>com.journaldev.spring.model.GroupSection</beans:value>
<beans:value>com.journaldev.spring.model.GroupNotes</beans:value>
<beans:value>com.journaldev.spring.model.GroupAttachments</beans:value>
<beans:value>com.journaldev.spring.model.Token</beans:value>
<beans:value>com.journaldev.spring.model.WaitingMembers</beans:value>
<beans:value>com.journaldev.spring.model.NoteHistory</beans:value>
<beans:value>com.journaldev.spring.model.GroupNoteHistory</beans:value>
<beans:value>com.journaldev.spring.model.Feedback</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL82Dialect
</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<beans:prop key="connection.pool_size">200</beans:prop>
<beans:prop key="c3p0.max_size">200</beans:prop>
<beans:prop key="c3p0.timeout">1000</beans:prop>
<beans:prop key="hibernate.jdbc.batch_size">100</beans:prop>
<beans:prop key="hibernate.order_updates">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
</beans:bean>
I hope my question was clear, if there is any doubt, please feel free to ask me. Thanks a lot. :-)
Take a look at Spring Session and its associated examples.
Browsers like Chrome on new tab or new window share the user session because use the same session cookies.
Check this or change your session approach.

spring Transaction management not working

I was using programmatic transaction management in spring, now I have switched to declarative transaction management.
SessionFactory
<beans:bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="packagesToScan" value="com.hcentive.cig.domain" />
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
<beans:prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
TransactionManager
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory">
<beans:ref bean="sessionFactory" />
</beans:property>
</beans:bean>
Now If run my code
#Override
#Transactional
public Request saveRequest(Request request) {
sessionFactory.getCurrentSession().save(request);
return request;
}
I get exception save is not valid without an active transaction
if I remove below line
<beans:prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</beans:prop>
I get
No CurrentSessionContext configured!
You definitely don't need this setting:
<beans:prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</beans:prop>
Spring Transaction Management layer should bind the Hibernate Session to the current running Thread.
The settings are fine, the only thing that might cause it comes from this statement of yours:
no it is getting called from service layer , and also I have tried
moving # transactional to service layer
You need to expose this method:
Request saveRequest(Request request);
through a Service interface, that you inject in any other component (web or other service layer beans).
To validate this, you can place a debug break-point in the saveRequest method implementation, and look for the TransactionInterceptor up the call-stack. If it's not there, then Spring couldn't wrap your method call into a Transaction Aspect processing logic.
Having your function annotated as Transactional is not necessarily enough. You also need to ensure that:
Your bean gets created via Spring (defined as #Component and found via componentScan OR declared in xml configuration)
The reference to your bean needs to be obtained through Spring dependency injection
For #Transactional to be effective you have to tell the Spring context that you want to use that. Annotations without a processor for that annotation is pretty useless. To enable the processor for the #Transactional annotation add <tx:annotation-driven /> to your context. (As explained here in the reference guide).
Your hibernate configuration is also problematic when using Spring you shouldn't mess around with the hibernate.current_session_context_class configuration property (unless you use some specific JTA provider but apparently you aren't). If you start setting that property you will break proper spring integration for transaction management. Spring already sets that property for you and your setting overrides the default.
Your configuration should look something like this.
<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="packagesToScan" value="com.hcentive.cig.domain" />
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref bean="sessionFactory" />
</beans:bean>
<tx:annotation-driven />

Categories