2015-05-21 15 views
10

Gần đây tôi đã chuyển từ Slick-2 sang Slick-3. Mọi thứ đang hoạt động rất tốt với slick-3. Tuy nhiên, tôi có một số vấn đề khi nói đến giao dịch. Tôi đã thấy các câu hỏi và mã mẫu khác nhau trong đó transactionallywithPinnedSession được sử dụng để xử lý giao dịch. Nhưng trường hợp của tôi hơi khác một chút. Cả hai transcationally và withPinnedSession có thể được áp dụng trên Query. Nhưng những gì tôi muốn làm là để vượt qua cùng một phiên để một phương pháp mà sẽ làm một số hoạt động và muốn bọc nhiều phương pháp trong cùng một giao dịch.Chia sẻ phiên cơ sở dữ liệu giữa nhiều phương thức trong Slick 3

Tôi có mã slick-2 bên dưới, tôi không chắc chắn cách thực hiện điều này bằng Slick-3.

def insertWithTransaction(row: TTable#TableElementType)(implicit session: Session) = { 
     val entity = (query returning query.map(obj => obj) += row).asInstanceOf[TEntity] 
     // do some operations after insert 
     //eg: invoke another method for sending the notification 
     entity 
} 

override def insert(row: TTable#TableElementType) = { 
    db.withSession { 
     implicit session => { 
     insertWithTransaction(row) 
     } 
    } 
} 

Bây giờ, nếu ai đó không quan tâm đến việc có giao dịch, họ chỉ có thể gọi phương thức insert(). Nếu chúng tôi cần thực hiện một số giao dịch, bạn có thể thực hiện giao dịch bằng cách sử dụng insertWithTransaction() trong khối db.withTransaction.

Đối với ví dụ:

db.withTransaction { implicit session => 
    insertWithTransaction(row1) 
    insertWithTransaction(row2) 
    //check some condition, invoke session.rollback if something goes wrong 
} 

Nhưng với trơn-3, transactionally có thể được áp dụng trên chỉ truy vấn. Điều đó có nghĩa, bất cứ nơi nào chúng ta cần làm một số logic tập trung sau khi chèn, nó là có thể. Mỗi nhà phát triển cần phải xử lý thủ công các tình huống đó một cách rõ ràng, nếu họ đang sử dụng các giao dịch. Tôi tin rằng điều này có khả năng gây ra lỗi. Tôi đang cố gắng để tóm tắt toàn bộ logic trong hoạt động chèn để người triển khai chỉ cần lo lắng về sự thành công/thất bại của giao dịch

Có cách nào khác, trong slick-3, trong đó tôi có thể chuyển cùng một phiên sang nhiều các phương thức để mọi thứ có thể được thực hiện trong phiên db duy nhất.

Trả lời

1

Bạn đang thiếu một cái gì đó: .transactionnaly không áp dụng cho Query, nhưng đến một DBIOAction. Sau đó, một DBIOAction có thể bao gồm nhiều truy vấn bằng cách sử dụng chế độ monadic.

Dưới đây là một ví dụ đến từ các tài liệu:

val action = (for { 
    ns <- coffees.filter(_.name.startsWith("ESPRESSO")).map(_.name).result 
    _ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*) 
} yield()).transactionally 

action bao gồm một truy vấn select và như nhiều delete truy vấn như hàng được trả về bởi truy vấn đầu tiên. Tất cả những gì tạo ra DBIOAction được thực hiện trong một giao dịch.

Sau đó, để chạy các hành động chống lại các cơ sở dữ liệu, bạn phải gọi db.run, như vậy, như thế này:

val f: Future[Unit] = db.run(action) 

Bây giờ, quay trở lại để dụ của bạn, giả sử bạn muốn áp dụng một truy vấn update sau khi chèn, bạn có thể tạo một hành động theo cách này

val action = (for { 
    entity <- (query returning query.map(obj => obj) += row) 
    _ <- query.map(_.foo).update(newFoo) 
} yield entity).transactionnaly 

Hy vọng điều đó sẽ hữu ích.

Các vấn đề liên quan