# Transactions and Open Session in View — Spring Boot

Source: https://www.skillbyai.com/en/spring-boot/j-tx

> Consistent writes, explicit boundaries.

## @Transactional on services

`@Transactional` on service methods makes their database work atomic: everything commits together or rolls back on a runtime exception. `readOnly = true` lets the driver and Hibernate optimise reads. Put transactions in the **service** layer, not controllers. Disable **open session in view** (`spring.jpa.open-in-view=false`, as the demo does) so lazy loading cannot silently run queries during JSON rendering outside transactions; Spring Boot warns when it is left enabled.

## Transactional service methods

This file is from a demo "shop" service generated by start.spring.io for Spring Boot 4.1.1 and Java 21 (Temurin 21.0.12), built with Maven 3.9.16; the project compiled and its tests passed. Reads are read-only transactions; create runs in a read-write transaction (the same file as the injection example).

```java
import org.springframework.transaction.annotation.Transactional;
public class ProductService {
    public ProductService(ProductRepository repository) {   // constructor injection
    @Transactional(readOnly = true)
    public Product get(long id) {
    @Transactional(readOnly = true)
    public List<Product> cheaperThan(BigDecimal max) {
    @Transactional
    public Product create(String name, BigDecimal price) {
```

## Beware self-invocation

@Transactional works through proxies, so calling a transactional method from inside the same class bypasses it.

**Quiz:** Where should @Transactional usually be placed?

- [ ] On JSON DTO records
- [x] On service-layer methods that define a unit of work
- [ ] On the main method
- [ ] On every getter

*Answer:* On service-layer methods that define a unit of work. Services own transaction boundaries.
