1

Environment :

Spring boot 1.4.0.RELEASE

Code :

I have a simple Spring REST web service set up as below :

Spring Data JPA Dao Layer:

public interface UserDao extends JpaRepository<User,Long>{ } 

Spring Service Layer :

@Service public class UserServiceImpl implements UserService{ @Autowired private UserDao userDao; @Override public void saveUser(User user){ userDao.save(user); } } 

Spring Controller :

@RestController public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/user", method = RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) public void saveUser(@RequestBody User user){ this.userService.saveUser(user); } } 

pom.xml extract :

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> 

Issue/Queries :

With above set up when I call UserController.saveUser , everything works fine and data gets saved to DB. I am using in memory H2 db .

So my questions are :

1)My service layer is NOT MARKED WITH @Transactional nor I am using any AOP config ?
So who is creating/managing transaction here ?

After debugging the application , it seems that Spring Data JPA Repository class has AOPProxy CGLIB semantics ? That means this class is running inside transaction . Is this the default behaviour if we don't make Spring Service as @Transactional ?

2)When Spring Boot is used , all of the below things are configured automatically for you based on classpath :

1)DataSource

2)Transaction Manager

If this is the case , I have seen a couple of tutorials where persistence config contains below : Why is this required then ? Should Spring boot not configure all of the below things automatically for you ?

 @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); em.setPackagesToScan(new String[] { "com.atul.domain" }); final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); em.setJpaProperties(additionalProperties()); return em; } @Bean public DataSource dataSource() { final DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); dataSource.setUrl(env.getProperty("jdbc.url")); dataSource.setUsername(env.getProperty("jdbc.username")); dataSource.setPassword(env.getProperty("jdbc.password")); return dataSource; } @Bean public JpaTransactionManager transactionManager() { final JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); return transactionManager; } 

1 Answer 1

3

1) Spring Data creates a transaction around calls to repository methods by default (see http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions). So, if your service layer is not marked with @Transactional, each repository call will have its own transaction by default (which is undesirable in many situations).

2) This extra configuration code is only needed if the default does not suffice for your needs. In your code example, I see nothing that you cannot configure with Spring Boot features, so this extra code is not really needed.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer. It works . I have one more query , I have made my service layer Transactional which wraps service layer around transactional proxy. But Dao layer is also around proxy . When proxy around Dao class will be removed ? There will be only one Transaction running which should be started from service layer
If you mean the repository interfaces with the DAO layer, it will always have a proxy, because that's the way how Spring creates the implementation for the interface on-the-fly.
The Spring Data repositories by default have a transaction type of REQUIRED, which means that they will run in the transaction that was already opened in the service layer or if they found none, they will open a new transaction.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.