In this post we are going to see about @Transactional(noRollbackFor = { SomeException.class }) example using Spring Boot. We will also see what is the effect of using noRollbackFor, how to use noRollBackFor attribute in the real-time scenario. Let’s see some points related to the noRollbackFor attribute.
Understanding Spring @Transactional(noRollbackFor = { SomeException.class })
As the name suggests (noRollBackFor), if we don’t want our transaction to be get rollbacked for any specific RuntimeException, we can use @Transactional noRollBackFor attribute.
Generally, if we are using @Transactional annotation with the method and some RuntimeException(for eg – NullPointerException, ClassCastException) comes, the transaction will get rollbacked(See @Transactional rollBackFor example for more details). This is the default behavior, if we don’t use noRollBackFor attribute.
Suppose some exception is good, we like that exception and we don’t want our transaction to get rollbacked even that exception occurs. For example, for any specific transaction, if NullPointerException comes, we don’t want to our transaction to be get rollbacked then we can use notRollBackFor as below.
We can use noRollbackFor attribute as a parameter with @Transnational annotation as follows.
@Transactional(noRollbackFor = { RuntimeException.class })
public void saveBook(Book book) {
// some logic
}
Let’s see an example where we will use noRollbackFor = {NullPoniterException.class}
@Transactional(noRollbackFor = {NullPoniterException.class})
public void saveBook(Book book) {
// some logic
}
Spring @Transactional noRollbackFor example using spring boot and Oracle.
Prerequisites.
- JDK 1.8
- Oracle 10g
- Eclipse
- maven
- postman
Step 1 – open eclipse and create maven project, Don’t forget to check ‘Create a simple project (skip) and click on next.
Step 2 – Fill all details as below and click on finish.
Step 3 – Replace the pom.xml with below code.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>springtransactionexample</groupId> <artifactId>springtransactionexample</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springtransactionexample</name> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> </dependencies> </project>
Step 4 – Create the below directory structure.
Step 5 – Define the following classes and interfaces.
Book.java
package com.springtransaction.entity; import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "book") public class Book { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int bookId; @Column(name="book_name") private String bookName; @Column(name="auther_name") private String autherName; @Column(name="price") private int price; public String getAutherName() { return autherName; } public void setAutherName(String autherName) { this.autherName = autherName; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public int getBookId() { return bookId; } public void setBookId(int bookId) { this.bookId = bookId; } }
BookService.java – interface
package com.springtransaction.service; import java.util.List; import org.springframework.stereotype.Component; import com.springtransaction.entity.Book; @Component public interface BookService { public void saveBook(Book book); }
BookRepository.java – interface
package com.springtransaction.repository; import java.io.Serializable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import com.springtransaction.entity.Book; @Repository public interface BookRepository extends CrudRepository<Book,Serializable> { }
BookServiceImpl.java
package com.springtransaction.serviceimpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.springtransaction.entity.Book; import com.springtransaction.repository.BookRepository; import com.springtransaction.service.BookService; @Service public class BookServiceImpl implements BookService { @Autowired private BookRepository bookRepository; @Transactional(noRollbackFor = {NullPointerException.class}) public void saveBook(Book book) { Book book1 = null; // save book book1 = bookRepository.save(book); String s1 = null; System.out.println(s1.hashCode()) } }
BookController.java
package com.springtransaction.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.springtransaction.entity.Book; import com.springtransaction.service.BookService; @RestController @RequestMapping("/book") public class BookController { @Autowired private BookService bookService; @RequestMapping(value = "/savebook",method = RequestMethod.POST) @ResponseBody public Book saveBook(@RequestBody Book book) { bookService.saveBook(book); return book; } }
JpaConfig.java
package com.springtransaction.config; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @Configuration @EnableJpaRepositories(basePackages = "com.springtransaction.repository") public class JpaConfig { }
SpringMainExample.java
package com.springtransaction.springtransaction; import org.hibernate.SessionFactory; import org.hibernate.jpa.HibernateEntityManagerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import com.springtransaction.entity.Book; import com.springtransaction.service.BookService; @SpringBootApplication(scanBasePackages={"com.springtransaction"}) @EntityScan("com.springtransaction.*") public class SpringMainExample { public static void main(final String[] args) { final ConfigurableApplicationContext configurableApplicationContext = SpringApplication .run(SpringMainExample.class, args); } }
And finally, we have application.properties
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:XE spring.datasource.username=SYSTEM spring.datasource.password=oracle1 spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver spring.datasource.testWhileIdle = true spring.datasource.validationQuery = SELECT 1 spring.jpa.show-sql = true spring.jpa.hibernate.ddl-auto =create spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.Oracle10gDialect server.port = 9091
We are good now. Let’s run the application.
Test from postman with below request data.
Let’s check the DB.
Even we have NullPointerException in our code, we have one record in the database. If you remove noRollbackFor = {NullPointerException.class} from @Transactional annotation, it will not save any record.
Real time scenario when to use @Transactinal noRollbackFor = {SomeException.class}.
We may have business requirement while login we want to store username and password, it doesn’t matter user is authorised or not. Suppose we have some custom exception according to our requirement i.e UserUnUthorizedException. Whenever some user login with the wrong username or password exception should come. Even user is not authenticated successfully, we may want to save the record in DB to know what credentials user is using. In this scenario, we can use noRollbackFor ={UserUnUthorizedException.class} attribute with @Transactional annotation.
The same way we can use for another different scenario where even exception comes we don’t want to get transaction rollbacked.
That’s all about @Transactional noRollbackFor example using spring boot.
You may like.
- Spring transaction management example using spring boot.
- @Transactional REQUIRED vs REQUIRES_NEW example in spring boot.
- @Transactional rollbackFor example using spring boot.
- @Transactional readonly true example in spring boot.
- @Transactional noRollbackForClassName example using spring boot
- @Transactional rollbackForClassName example using spring boot.
Spring @Transactional noRollBackFor docs.
Summary – We have seen how to use @Transactional noRollbackFor attribue.