liveBook · Manning

Upsert

As explained in Akka in Action, Second Edition

An upsert is a database operation that inserts a record when no matching record exists and updates the matching record otherwise.

An upsert combines insertion and updating: it inserts a record when no matching data exists, or updates the existing record otherwise. In a projection, this lets aggregated event data move from a journal into a separate database while reading and writing remain decoupled. section 10.2.1

Counting cargo per container

A repository can upsert a container’s cargo count. The first CargoAdded event creates (containerId, 1); later events for the same container update the row by adding one to its existing count. The statement runs inside a database transaction, which can commit or roll back. section 10.3.2

A projection can apply the operation through a small processing pipeline:

  • Read events from the journal and wrap them in event envelopes. section 10.2.1
  • Match CargoAdded events and delegate storage to a repository. section 10.3.2
  • Insert a missing row or update the matching row with the new aggregate value. section 10.3.2
Listing 10.7 Repository Implementation
trait CargosPerContainerRepository {                              #1
 
  def addCargo(containerId: String, session: ScalikeJdbcSession): Unit
}
 
class CargosPerContainerRepositoryImpl extends CargosPerContainerRepository {
 
  override def addCargo(
      containerId: String,
      session: ScalikeJdbcSession): Unit = {
    session.db.withinTx { implicit dbSession =>                   #2
      sql"""INSERT INTO cargos_per_container (containerId, carg   #3
              VALUES ($containerId, 1)
                ON CONFLICT (containerId) DO
              UPDATE SET cargos = cargos_per_container.cargos + 1
                  """.executeUpdate().apply()
    }
}

Browse the repository implementation to see the INSERT ... ON CONFLICT statement that creates or increments a container record. section 10.3.2

How Akka in Action, Second Edition covers it

How deep it goes
Defines insert-versus-update behavior and demonstrates transactional SQL, stopping short of database-library details.
Examples
Uses a cargo-per-container projection that creates a count and increments it for later CargoAdded events.
What it assumes
Assumes event envelopes, projections, SQL, and repository structure while defining upsert behavior directly.
What you can do after
Apply it via ScalikeJDBC to create or update aggregate rows inside a projection transaction.
How it connects
Connects persistence queries, projections, event journals, repositories, and database transactions.

Also explained in

Compare how 3 books explain upsert →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Akka in Action, Second Edition. The section links point to the parts of the book it draws on.