In my application I need to store some data to the RDBMS DB and some data to the MongoDB in the same transaction and I am using Spring JTA for my RDBMS transactions.
I am new to MongoDB and i am not sure that will this Spring JTA supported by MongoDB. What's the way or api to handle a transaction programmaticaly in MongoDB as MongoDB doesn't support transaction.
As like working with RDBMS and by annotating a method #Transactional, all operation's in method done as a single atomic operations and if an error occur automatic rollback done by Spring JTA but how we can achieve this using MongoDB?
You can use atomic operations or two-phase commit. Also Check this out. This article explains about plugin developed for Mongo that promises not only transactions but also a boosting in performance.
Related
On Using Spring JDBC which works very well and has some improvements over JPA when using Batch processing.
I would love to learn why to use Spring Data JDBC when you already have Spring JDBC.
I would love to learn why to use R2DBC when you already have Spring JDBC.
The three technologies work on different abstraction levels.
R2DBC is an alternative to JDBC. It is reactive, i.e. non-blocking. You send a statement to the server, continue to work and eventually receive the results as an event. It is often used for the ability to better scale. But using it is more complex because it is asynchronous and basically your complete application should be too in order to get the benefits. As with JDBC you probably don't want to use it on its own.
Spring JDBC is comparable to Spring R2DBC both hide some of the more tedious details of the underlying technology. They both offer pretty much full access to the underlying technology and just give you a more pleasant developer experience.
Spring Data JDBC is an Object Relational Mapper (ORM) based on the Repository abstraction. For the reactive world there is also Spring Data R2DBC which shares code and properties with Spring Data JDBC. It is basically a replacement of Spring Data JPA. For a comparison of Spring Data JDBC and Spring Data JPA see https://stackoverflow.com/a/42488593/66686.
The Repository abstraction of Spring Data comes from Domain Driven Design. You can think of a Repository as a collection that is backed by some persistence mechanism. The elements of that collections are not just entities but aggregates, which belong together and don't make sense on their own. A typical example is a Purchase Order with its Line Items. A Line Item doesn't make much sense without its Purchase Order.
This approach puts some constraints on the design of your domain model. In return you get a nice clean structure for you domain model. Both Spring Data JDBC and Spring Data R2DBC allow to combine them freely with Spring JDBC and Spring R2DBC. This is very different for JPA and everything build on it, because JPA has a cache as integral part of the system which will lead to interesting effects when you mix JPA and direct JDBC access within a single transaction.
See the following table for an overview of the different technologies discussed.
Stack
JDBC to Spring Data JDBC
R2DBC to Spring Data R2DBC
JDBC to Spring Data JPA
Underlying API
JDBC
R2DBC
JDBC
Usability Layer
Spring JDBC
Spring R2DBC
Spring ORM (*)
ORM
Spring Data JDBC
Spring Data R2DBC
JPA
Repository Abstraction
Spring Data JDBC
Spring Data R2DBC
Spring Data JPA
Communication Style
synchronous
reactive
synchronous
(*) Spring ORM sits on top of JPA or other Spring independent ORM technologies, so in this table it kinda should be below JPA.
When you would use R2DBC is easy, it’s when you are building an application that is non-blocking. Everything in the stack has to be non-blocking, including the database driver. JDBC is inherently blocking, people try schemes to get around it but it is not great. If you aren’t building a non-blocking application you wouldn’t use R2DBC.
For the part about when to use spring data JDBC, it looks like it gives you a simpler way to create repositories and map data, as long as you’re ok with their opinionated framework, you are ok with not having all the complex mappings you get with JPA, and you want the DDD concepts (like aggregate root). Otherwise Spring JDBC requires more code to create your data access objects but may give more control. https://docs.spring.io/spring-data/jdbc/docs/2.2.4/reference/html/#reference describes more about why to use Spring Data JDBC. It is simplicity vs control.
I am new to reactive programming I have started using webflux, previously I work on spring boot there I have used hibernate as a ORM framework. My doubt is what is replace of hibernate in reactive stack , which framework I have to use to connect & implement database logic.
I am using mongoDB.
Thanks in advance.
you have to use either R2DBC or Hibernate reactive.
if you migrating an old service from spring boot to webflux, I recommended you to use Hibernate reactive.
when you use R2DBC, you can't use hibernate mappings and annotations.
according to hibernate reactive documentation:
When using a stateless session, you should be aware of the following additional limitations:
persistence operations never cascade to associated instances,
changes to #ManyToMany associations and #ElementCollections cannot be
made persistent, and
operations performed via a stateless session bypass callbacks.
Hibernate is based on JDBC. JDBC is blocking. Blocking APIs don't work well in reactive stacks. Also, Hibernate under the hood uses ThreadLocals which makes it even worse candidate for reactive applications.
For Webflux, as the alternative to Hibernate you should look into Spring Data R2DBC which does the basic database result to Java object mapping, but keep in mind that it's not a full fledge ORM like Hibernate.
You may also want to give it a try to Hibernate Reactive. With this you can use the power of Hibernate mappings in a reactive non blocking way. One thing that will not work though (at least not yet) is declarative transaction management with #Transactional.
It depends on what database driver you are using.
If using the jdbc driver to talk to your database, then yes you can use hibernate. But important to note is that the JDBC spec is blocking so every call to the database will be blocking, and must be placed on its own scheduler (thread) and you will most likely not get the full performance benefits of a fully reactive application.
If you want a fully reactive application you must use a database driver that supports the R2DBC protocol. Hibernate does not support R2DBC so can not be used if you want a fully reactive application.
Hibernate is most commonly used with relation database such as mysql, postgres, oracle etc and not NoSql databases such as monogDB.
If you are using MongoDB then there is full support for R2DBC and there is no need for hibernate.
I'm currently using the #Transactional annotation to save data to a database, and would like to know how to change the transaction so it affects other resources like message queues. I didn't set up beans or anything to make dealing with the database transactional - I just added the #Transactional annotation and nothing else.
You are thinking to enter complicated and slow world called two phase commit transactions. For such case you would need to use distributed transactions manager like Atomikos. JEE has JTA (Java Transaction API) abstractions for it.
I would suggest to avoid this world as much as possible, because of slowness.
Here are few Spring Boot examples I created. They combine distributed transactions with database and JMS queue.
Combining even more than two data sources into distributed transactions would be extremely slow.
Is it possible to make operations on EhCache make part of Spring's JpaTransactionManager?
During the transaction I'm doing some operations (put/evict) on EhCache and I want them to be committed when transaction succeeds and rollbacked when transaction fails. Just like the regular behavior on a database transaction.
How can I achieve this using Spring and Hibernate?
Do I need a JTA transaction manager for this?
I'm using Oracle 11g for my database and its Oracle Streams AQ feature as JMS implementation.
For all I know, it should be possible to implement a Spring based message-driven POJO (MDP) that uses the same data source for both transactional data access and JMS transactions -- all without XA-Transactions (IIRC, this was marketed as a feature of SpringSource Advanced Pack for Oracle).
Is this possible using Hibernate as well? Ideally, my MDP would start a JMS transaction and read a message from a queue, then re-use the transaction for data access through Hibernate. If anything goes wrong, the JMS and database transaction would both be rolled back, without using 2-phase commit (2PC).
I'm not much of a transaction guru, so before I start digging deeper, can anyone confirm that this is possible and makes sense as well?
Update:
What I want is an implementation of the Shared Transaction Resource pattern. The sample code demonstrates it for ActiveMQ and JDBC, but I need to use Oracle Streams AQ and Hibernate.
Update2:
The SpringSource Advanced Pack for Oracle has been open sourced as part of Spring Data JDBC and it "provides the option of using a single local transaction manager for both
database and message access without resorting to expensive distributed 2-phase commit
transaction management".
2PC shouldn't be necessary, as you say, since the appserver should take care of it. However, you'll pretty much have to use JTA (i.e. JavaEE container) transactions, rather than vanilla DataSource transactions, since JMS only works with JTA.
This isn't a big deal, it's just a bit more fiddly:
Your Spring config should use
<jee:jndi-lookup/> to get a
reference to your container's
DataSource, and you inject that
data source into your spring-managed
hibernate SessionFactory.
You then need to introduce a transaction manager into the context (<tx:jta-transaction-manager/> should work in most app-servers).
In your Spring JMS MessageListenerContainer, plug the above transaction manager reference into it.
Does that all make sense, or should I elaborate? This setup should ensure that the container-managed transactions are held across JMS and Hibernate interactions.