11 Transactions and concurrency


This chapter covers

  • Defining database and system transaction essentials
  • Controlling concurrent access with Hibernate and JPA
  • Using non-transactional data access
  • Managing transactions with Spring and Spring Data

In this chapter, we finally talk about transactions: how we create and control concurrent units of work in an application. A unit of work is an atomic group of operations. Transactions allow us to set unit of work boundaries and help us isolate one unit of work from another. In a multiuser application, we may also be processing these units of work concurrently.

To handle concurrency, we first focus on units of work at the lowest level: database and system transactions. You’ll learn the APIs for transaction demarcation and how to define units of work in Java code. We’ll demonstrate how to preserve isolation and control concurrent access with pessimistic and optimistic strategies. The overall architecture of the system impacts the scope of a transaction. A bad architecture may lead to fragile transactions.

Then, we analyze some special cases and JPA features, based on accessing the database without explicit transactions. Finally, we’ll demonstrate how to work with transactions with Spring and Spring Data.

Let’s start with some background information.

11.1 Transaction essentials

11.1.1 ACID attributes

11.1.2 Database and system transactions

11.2 Controlling concurrent access

11.2.1 Understanding database-level concurrency

11.2.2 Optimistic concurrency control

11.2.3 Explicit pessimistic locking

11.2.4 Avoiding deadlocks

11.3 Non-transactional data access

11.3.1 Reading data in auto-commit mode

11.3.2 Queueing modifications

11.4 Managing transactions with Spring and Spring Data

11.4.1 Transaction propagation

11.4.2 Transaction rollback

11.4.3 Transaction properties

11.4.4 Programmatic transaction definition

11.4.5 Transactional development with Spring and Spring Data

11.5 Summary