2015-10-15 65 views
2

我试图有一个函数返回更新的对象之后,数据库现在在查询上运行更新方法,但我无法弄清楚如何成功返回对象。这是我用我发现的例子写的函数,但是我想扩展q.update(cat)来返回Future [Cat]。有趣的更新返回更新的对象

def update(id: Long, cat: Cat): Future[Unit] = db.run { 
    val q = for { c <- cats if c.id === id } yield c 
    q.update(cat).map(_ =>()) 
} 
+0

你可能想看看[这个问题及其答案](http://stackoverflow.com/questions/30212785/slick-3-0-update-columns-in-a-table-and-return-whole -table-object) – Shadowlands

+0

作为一个快速的解决方案,你可以在修改后的值上复制cat实体,只有在操作成功时才​​返回。 –

+0

我不认为复制输入将适用于通过触发器更新的字段(lastUpdated timestamp等)。这对Po​​stgresql数据库非常常见。 – Nick

回答

1

你应该尝试以下操作:

def update(id: Long, cat: Cat): Future[Option[Cat]] = db.run { 
    cats.filter(_.id === id).update(cat).map { 
    case 0 => None 
    case _ => Some(cat) 
    } 
} 

您应该返回Future[Option[Cat]],而不是一个Future[Cat],因为提供ID猫可能不存在(在update方法返回0值即可)。违反完整性约束将导致FutureFailure

+0

我认为这可能适用于这种特定情况,但是 - 1.如果没有用户使用此ID,更新是否真的“失败”?可能不会,实际上这就是您的“updatesCount”0个案涵盖的内容。 2.我不认为这个数据库操作序列会导致锁定,所以即使你在一个事务中运行,你也可能不会这样做......这几乎是一个更新,然后是一个选择,包装在一个没有意义的交易。如果我错了,请纠正我,但我对交易有类似的误解。它们为失败提供回滚,但我认为这个Q更关于原子更新/读取。 – jm0

+0

我以一种不使用事务的方式简化了我的解决方案,但是早期的解决方案仍然可以按预期工作。回答你的问题: 1.你是对的 - 在我的文章中,'fail'这个词有点误导,因为这种情况不会返回'Failure'(但是,如果你将'DBIO.successful'替换成'与'DBIO.failed')。 2.由于它是一个更新后跟一个选择,那个事务并不是没有意义的(现在整个事情就是ACID)。从文档:'如果包装的Action成功,则事务被提交,或者如果包装的Action失败,则返回。 –

+0

很酷。我得到你说的我的观点是,只是没有任何更新/选择序列会导致事务回滚。即使你在0个受影响的行中抛出失败,你真的在​​做什么,回滚没有任何更新?我相信交易中不存在竞争条件的保证(您可以更新和选择,您选择的内容可能已被其他线程更改过),只是简单地说每条线都将单独执行并在任何情况下回滚失败。在某些情况下,确切的状态是重要的,其他情况可能不会 – jm0