0Pricing
Scala for Backend Engineering & Functional Programming · 강의

삽입과 갱신

함수형 방식으로 데이터를 작성해 보세요.

삽입과 갱신은(는) CoddyKit의 무료 Scala for Backend Engineering & Functional Programming 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Scala for Backend Engineering & Functional Programming 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Scala for Backend Engineering & Functional Programming 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Update0 for Writes

Writes use the same sql interpolator, but you call .update to get an Update0 instead of .query.

Running .run on an Update0 returns a ConnectionIO[Int]: the number of affected rows.

import doobie.implicits._

def insert(name: String, age: Int): ConnectionIO[Int] =
  sql"insert into users (name, age) values ($name, $age)".update.run

Affected Row Counts

The Int from .run is the JDBC update count. For an UPDATE or DELETE it tells you how many rows matched.

You can branch on it to detect, for example, an update that matched no rows.

def deactivate(id: Long): ConnectionIO[Int] =
  sql"update users set active = false where id = $id".update.run

Returning Generated Keys

To get an auto-generated primary key, use .withUniqueGeneratedKeys, naming the columns the database returns.

This runs the insert and reads back the generated values in one round trip.

def insertReturningId(name: String, age: Int): ConnectionIO[Long] =
  sql"insert into users (name, age) values ($name, $age)"
    .update
    .withUniqueGeneratedKeys[Long]("id")

Returning a Whole Row

You can return several generated or defaulted columns at once by reading them into a tuple or case class.

This is great for capturing server-side defaults like timestamps right after insert.

case class User(id: Long, name: String, createdAt: java.time.Instant)

def create(name: String): ConnectionIO[User] =
  sql"insert into users (name) values ($name)"
    .update
    .withUniqueGeneratedKeys[User]("id", "name", "created_at")

The Update Class for Batches

Update[A] is a prepared, parameterized statement you can run many times. You define the SQL once with ? placeholders and supply values of type A.

It is built from a SQL string plus a Write[A] instance.

val ins: Update[(String, Int)] =
  Update[(String, Int)]("insert into users (name, age) values (?, ?)")

Efficient Batch Inserts

updateMany sends a whole collection in one JDBC batch, far faster than looping single inserts.

It returns the total number of affected rows. Use it whenever you load many rows at once.

val rows = List(("Ada", 36), ("Linus", 54))

val batch: ConnectionIO[Int] = ins.updateMany(rows)

Batch Insert with Keys

Update can also stream generated keys for a batch via updateManyWithGeneratedKeys, giving back a row per inserted record.

This combines bulk loading with reading back assigned identifiers.

import fs2.Stream

val keyed: Stream[ConnectionIO, Long] =
  ins.updateManyWithGeneratedKeys[Long]("id")(rows)

Upserts with ON CONFLICT

Database-specific upserts work fine through Doobie. On PostgreSQL you write insert ... on conflict ... do update as normal SQL.

Doobie just binds your parameters; the upsert semantics belong to the database.

def upsert(email: String, name: String): ConnectionIO[Int] =
  sql"""insert into accounts (email, name) values ($email, $name)
         on conflict (email) do update set name = excluded.name"""
    .update.run

Write Instances and Defaults

Parameters are encoded with the Write[A] typeclass, derived for primitives, tuples, and case classes. Each field needs a Put instance.

If you omit a column from the insert, the database applies its DEFAULT, which is how generated timestamps appear.

case class NewUser(name: String, age: Int)

val mk = Update[NewUser](
  "insert into users (name, age) values (?, ?)"
)

Custom Column Mappings with Meta

To persist a custom type, define a Meta[A] by mapping it to an existing column type with imap (or timap).

A Meta provides both reading and writing, so the type works in queries and updates alike.

import doobie.util.meta.Meta

case class UserId(value: Long)

implicit val uidMeta: Meta[UserId] =
  Meta[Long].imap(UserId.apply)(_.value)

Deletes Are Updates Too

DELETE statements also use .update.run and return the count of removed rows.

Treating inserts, updates, and deletes uniformly as Update0 keeps the API small and composable.

def purgeInactive: ConnectionIO[Int] =
  sql"delete from users where active = false".update.run

Quick Check

Pick the most efficient approach.

Recap

Writes use .update to produce an Update0; .run returns affected rows and .withUniqueGeneratedKeys reads back generated values.

For bulk work, Update[A].updateMany batches efficiently. Custom types get Meta instances, and upserts are just normal database SQL bound by Doobie.

자주 묻는 질문

“삽입과 갱신” 강의는 무료인가요?

네 — “삽입과 갱신” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Scala for Backend Engineering & Functional Programming 강의 전체를 잠금 해제할 수 있습니다. Scala for Backend Engineering & Functional Programming 강의에는 총 4개의 강의가 포함되어 있습니다.

“삽입과 갱신”에서 뭘 배우나요?

함수형 방식으로 데이터를 작성해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Scala for Backend Engineering & Functional Programming을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Scala for Backend Engineering & Functional Programming을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Scala for Backend Engineering & Functional Programming은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“삽입과 갱신” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Scala for Backend Engineering & Functional Programming 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Scala for Backend Engineering & Functional Programming 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Transactor로 연결하기
  2. 쿼리 실행하기
  3. 삽입과 갱신
  4. 트랜잭션 조합하기
← Scala for Backend Engineering & Functional Programming(으)로 돌아가기