Now, let's talk about transactions.
This is a huge topic and beyond the scope of this course,
but let's look at the essentials.
So, what happens when a method is transactional?
Now, the method executes inside of a transaction.
If anything goes wrong in the middle of the method execution,
the transaction will be rolled back.
Otherwise, it will be committed.
So, for example, let's say there were 100 comments in the database,
and while this method is being executed, 30 of them were successfully streamed.
But then something happens in the middle of it,
and it could not read from the database anymore.
Since this method runs within a transaction,
the whole method will fail instead of returning 30 comments,
and that prevents us from getting an incomplete list of comments.
Spring provides comprehensive transaction support.
And here's a very simplified overview of how it works.
Spring framework's transaction support is enabled via AOP proxies.
So, the caller of the method invokes the proxy, not the target.
And at this point, a transaction is created.
Then the target method is invoked.
And on the way back, either the transaction is committed or rolled back.
How do we enable Spring's transaction management?
Typically, it is enabled using "@EnableTransactionManagement annotation",
or it could be done via XML as well.
But this is a Spring Boot application, so most of the configuration is done for me.
Because I have Spring Data libraries in the classpath,
transaction management is enabled by the framework.
So, I don't have to do anything to enable transaction management.
In order to apply transaction management,
all you have to do is add the "@Transactional annotation".
Now let's look at the annotation.
The "@Transactional annotation is metadata that specifies an interface, class, or method,
must have transactional semantics.
For example, start applying a method to a class,
For example, start a brand new read-only transaction when this method is invoked,
suspending any existing transaction.
There are quite a few settings that can be applied to this annotation.
This table from the documentation lists all of them.
First, there is value, which specifies the transaction manager to be used.
Then there is propagation.
These are the transaction propagation behaviors defined by the propagation inner.
Let's look at a couple of them.
First, the default one, which is required,
supports a current transaction, creates a new one if none exists.
If there is a transaction already started, then this method will execute within that,
otherwise a new one will be created.
Requires new.
Creates a new transaction and suspend the current transaction if one exists.
The next attribute I want to look at is read-only, which is a boolean.
What happens when the read-only attribute is set to true?
The default is false by the way.
Spring doesn't handle persistence, so it cannot define exactly what read-only should do.
So this is just a hint to the provider, which in this case is Hibernate.
According to the documentation, if using Hibernate as the JPA provider,
when read-only flag is set to true,
flash mode on the Hibernate session will be set to never, preventing any changes to data.
Following is an excerpt from the Spring Data documentation which states this.
It's definitely reasonable to use transactions for read-only queries,
and we can mark them as such by setting the read-only flag.
This will not however act as check that you do not trigger a manipulating query,
although some databases reject insert and update statements inside a read-only transaction.
The read-only flag instead is propagated as
hint to the underlying JDBC driver for performance optimizations.
Furthermore, Spring will perform some optimizations on the underlying JPA provider.
Example, when used with Hibernate, the flash mode is set to never
when you configure a transaction as read-only, which causes Hibernate to skip dirty checks.
A noticeable improvement on large objectories.
Next is timeout, in which you can give the number of seconds before timeout.
And then there is rollback4, which is an array of classes extending from throwable.
These are the exceptions that must cause a rollback.
The rest of the attributes are rollback4 class name, no rollback4,
no rollback4 class name, for which you can take a look if you want to use them.
Spring transaction management also supports the AtTransactional annotation from Java,
as a drop-in replacement for the AtTransactional annotation provided by Spring.
But it lacks some of the settings available in the one from Spring such as
read-only and timeout, which are quite useful.
So, I would use the Spring's Transactional annotation instead of the one from Java.