[SCALA] 하지가 슬릭 3.0.0에있는 경우 삽입
SCALA하지가 슬릭 3.0.0에있는 경우 삽입
내가하지가 존재하는 경우 삽입하기 위해 노력하고있어, 나는, 2.0 1.0.1이 게시물을 발견했다.
나는 조각 3.0.0의 문서에서 트랜잭션 사용 발견
val a = (for {
ns <- coffees.filter(_.name.startsWith("ESPRESSO")).map(_.name).result
_ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*)
} yield ()).transactionally
val f: Future[Unit] = db.run(a)
난 안가이 구조에 존재하는 경우 삽입에서 로직을 작성하기 위해 사투를 벌인거야. 나는 슬릭에 새로 온 사람과 스칼라와 약간의 경험이 있습니다. 이것은하지 트랜잭션 외부에 존재하는 경우 삽입 할 내 시도입니다 ...
val result: Future[Boolean] = db.run(products.filter(_.name==="foo").exists.result)
result.map { exists =>
if (!exists) {
products += Product(
None,
productName,
productPrice
)
}
}
하지만 내가 어떻게 트랜잭션 블록이 배치해야합니까? 이것은 내가 갈 수있는 먼 :
val a = (for {
exists <- products.filter(_.name==="foo").exists.result
//???
// _ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*)
} yield ()).transactionally
미리 감사드립니다
해결법
-
==============================
1.하지 쿼리를 존재하는 경우 ... 하나의 인서트를 사용하는 것이 가능하다. 이것은 여러 데이터베이스 라운드 트립과 경쟁 조건을 방지 (트랜잭션 격리 수준에 따라 충분하지 않을 수 있습니다).
하지 쿼리를 존재하는 경우 ... 하나의 인서트를 사용하는 것이 가능하다. 이것은 여러 데이터베이스 라운드 트립과 경쟁 조건을 방지 (트랜잭션 격리 수준에 따라 충분하지 않을 수 있습니다).
def insertIfNotExists(name: String) = users.forceInsertQuery { val exists = (for (u <- users if u.name === name.bind) yield u).exists val insert = (name.bind, None) <> (User.apply _ tupled, User.unapply) for (u <- Query(insert) if !exists) yield u } Await.result(db.run(DBIO.seq( // create the schema users.schema.create, users += User("Bob"), users += User("Bob"), insertIfNotExists("Bob"), insertIfNotExists("Fred"), insertIfNotExists("Fred"), // print the users (select * from USERS) users.result.map(println) )), Duration.Inf)
산출:
Vector(User(Bob,Some(1)), User(Bob,Some(2)), User(Fred,Some(3)))
생성 된 SQL :
insert into "USERS" ("NAME","ID") select ?, null where not exists(select x2."NAME", x2."ID" from "USERS" x2 where x2."NAME" = ?)
여기 GitHub의에서 전체 예제
-
==============================
2.이것은 내가 생각 해낸 버전입니다 :
이것은 내가 생각 해낸 버전입니다 :
val a = ( products.filter(_.name==="foo").exists.result.flatMap { exists => if (!exists) { products += Product( None, productName, productPrice ) } else { DBIO.successful(None) // no-op } } ).transactionally
그것은의 조금 예를 들어이 삽입 또는 기존 개체를 반환하는 것이 유용 할 것입니다,하지만 부족하다.
완성도를 들어, 테이블 정의에 여기 :
case class DBProduct(id: Int, uuid: String, name: String, price: BigDecimal) class Products(tag: Tag) extends Table[DBProduct](tag, "product") { def id = column[Int]("id", O.PrimaryKey, O.AutoInc) // This is the primary key column def uuid = column[String]("uuid") def name = column[String]("name") def price = column[BigDecimal]("price", O.SqlType("decimal(10, 4)")) def * = (id, uuid, name, price) <> (DBProduct.tupled, DBProduct.unapply) } val products = TableQuery[Products]
내가 매핑 테이블을 사용하고,이 솔루션은 작은 변화와 함께, 튜플도 작동합니다.
그것은이 작업 삽입 무시 년대 설명서에 따라 선택적으로 ID를 정의 할 필요가 없습니다 것을 유의하십시오 :
그리고 여기 방법 :
def insertIfNotExists(productInput: ProductInput): Future[DBProduct] = { val productAction = ( products.filter(_.uuid===productInput.uuid).result.headOption.flatMap { case Some(product) => mylog("product was there: " + product) DBIO.successful(product) case None => mylog("inserting product") val productId = (products returning products.map(_.id)) += DBProduct( 0, productInput.uuid, productInput.name, productInput.price ) val product = productId.map { id => DBProduct( id, productInput.uuid, productInput.name, productInput.price ) } product } ).transactionally db.run(productAction) }
(이 솔루션에 저를 향하게를위한 Google 그룹 스레드에서 감사 마태 복음 Pocock).
-
==============================
3.나는 외모보다 완벽한 솔루션으로 실행했습니다. 에센셜 슬릭 북의 삽입을 통해 제 3.1.7 더 많은 제어 예제를 가지고있다.
나는 외모보다 완벽한 솔루션으로 실행했습니다. 에센셜 슬릭 북의 삽입을 통해 제 3.1.7 더 많은 제어 예제를 가지고있다.
끝에서 당신은 떨어지게를 같이 얻을 :
val entity = UserEntity(UUID.random, "jay", "jay@localhost") val exists = users .filter( u => u.name === entity.name.bind && u.email === entity.email.bind ) .exists val selectExpression = Query( ( entity.id.bind, entity.name.bind, entity.email.bind ) ).filterNot(_ => exists) val action = usersDecisions .map(u => (u.id, u.name, u.email)) .forceInsertQuery(selectExpression) exec(action) // res17: Int = 1 exec(action) // res18: Int = 0
-
==============================
4.매끄러운 3.0 수동 삽입 조회 부 (http://slick.typesafe.com/doc/3.0.0/queries.html)에있어서, 삽입 된 값은 이하와 같은 ID로 반환 될 수있다 :
매끄러운 3.0 수동 삽입 조회 부 (http://slick.typesafe.com/doc/3.0.0/queries.html)에있어서, 삽입 된 값은 이하와 같은 ID로 반환 될 수있다 :
def insertIfNotExists(productInput: ProductInput): Future[DBProduct] = { val productAction = ( products.filter(_.uuid===productInput.uuid).result.headOption.flatMap { case Some(product) => mylog("product was there: " + product) DBIO.successful(product) case None => mylog("inserting product") (products returning products.map(_.id) into ((prod,id) => prod.copy(id=id))) += DBProduct( 0, productInput.uuid, productInput.name, productInput.price ) } ).transactionally db.run(productAction) }
from https://stackoverflow.com/questions/30706193/insert-if-not-exists-in-slick-3-0-0 by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라 선물에 의해 반환 된 액세스 값 (0) | 2019.11.15 |
---|---|
[SCALA] 분리 대 검증 (0) | 2019.11.15 |
[SCALA] 문자열에 FlatMap 대지도 (0) | 2019.11.15 |
[SCALA] 스칼라 2.10 반사, 나는 경우 클래스의 경우 클래스, 즉 필드 목록에서 필드 값을 추출 어떻게 (0) | 2019.11.15 |
[SCALA] 스칼라의 형식 매개 변수로 표현 형식의 인스턴스를 인스턴스화하는 방법 (0) | 2019.11.15 |