SoFunction
Updated on 2025-04-05

Spring JPA transaction management and custom operation instance analysis (latest recommendation)

In the Spring framework, data persistence operations are often closely related to transaction management. This article will explore the transaction management mechanism in Spring Data JPA in depth, and combine specific examples to show how to customize transaction behavior to meet different business needs.

Transaction Management in Spring JPA

In Spring Data JPA, the defaultCrudRepositoryRealization isSimpleJpaRepository. This class passes@TransactionalAnnotation supports transaction management, wherereadOnly = trueProperties mean that by default all methods are executed in read-only transactions. For write operations,deleteByIddeleteAlletc. They pass@TransactionalAnnotations override read-only behavior, so that these methods are executed in a write transaction.

@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
    @Transactional
    public void deleteById(ID id) {...}
    // Other write operations}

Customize Repository transaction behavior

To customize transaction settings, we can override specific methods and add@Transactionalannotation. For example, we candeleteByIdMethod sets a timeout:

public interface EmployeeRepository extends CrudRepository<Employee, Long> {
    @Transactional(timeout = 10)
    @Override
    public void deleteById(ID id);
}

Using transactions outside Repository

Use transactions outside of Repository and need to be added on the configuration class@EnableTransactionManagementannotation:

@Configuration
@ComponentScan
@EnableTransactionManagement
public class AppConfig {
    // ...
}

Then, we can use it in the service class@TransactionalAnnotation to manage transactions:

@Service
public class MyExampleBean{
    @Transactional
    public void saveChanges() {
        (..);
        (..);
        .....
    }
}

Case Study

Entity definition

@Entity
public class Employee {
    @Id
    @GeneratedValue
    private Long id;
    @Column(unique = true)
    private String name;
    private String dept;
    private int salary;
    //Omit other fields and methods}

Repository definition

public interface EmployeeRepository extends CrudRepository<Employee, Long> {
    @Transactional(timeout = 10)
    @Override
    <S extends Employee> S save(S s);
}

Client Operation

@Component
public class ExampleClient {
    @Autowired
    private EmployeeRepository repo;
    public void findEmployees() {
        (" -- finding all employees --");
        ().forEach(::println);
    }
    @Transactional
    public void saveEmployees() {
        (("Mike", "Sale", 1000));
        (("Diana", "Admin", 3000));
        (("Diana", "IT", 3200)); // This will trigger an exception    }
}

On the abovesaveEmployeesIn the method, we try to save employees with duplicate names. becauseEmployeePassed in entity class@Column(unique = true)A unique column is specified, the last save call will fail and the entire transaction will be rolled back. If not used@TransactionalNote that the first two employees will still be saved, that is, the entire saving process will not be atomic.

JavaConfig configuration

@EnableJpaRepositories
@ComponentScan
@Configuration
@EnableTransactionManagement
public class AppConfig {
    @Bean
    EntityManagerFactory entityManagerFactory() {
        EntityManagerFactory emf =
                ("example-unit");
        return emf;
    }
    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager txManager = new JpaTransactionManager();
        (entityManagerFactory());
        return txManager;
    }
}

Main category

public class ExampleMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext();
        ExampleClient exampleClient = ();
        try {
            ();
        } catch (Exception e) {
            (e);
        }
        ();
        EntityManagerFactory emf = ();
        ();
    }
}

If notsaveEmployeesMethod use@TransactionalAnnotation, then even if a unique constraint exception is triggered, the data of the first two employees will still be saved, which violates the atomic principle of the transaction.

Through the above analysis, we can see the flexibility and power of Spring JPA transaction management, as well as how to meet complex business needs through custom transaction behavior.

This is the end of this article about Spring JPA transaction management and custom operation instance analysis. For more related Spring JPA transaction management content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!