鉴于 runDB 的以下定义,第二个插入是否会在第一个失败时回滚?
Given the below definition of runDB, will the second insert rollback upon failure of the first?
我使用 Yesod 作为框架,使用 postgresql 作为数据库,并且有以下 runDB
的定义。查看 Yesod 站点上的文档,我有一种预感,以下列方式使用 runDB
将导致第一个 insert
在第二个失败时回滚。我对吗。如果没有,我该如何调用回滚?
instance YesodPersist App where
<snip>
runDB action = do
master <- getYesod
runSqlPool action $ appConnPool master
addKitteh :: Kitteh -> Handler (Either StoreError StoreResult)
addKitteh (Kitteh desc color size photo) = do
data_key <- runDB $ do
data_key <- insert (KittehDesc desc color size)
insert (KittehPic data_key photo)
...
编辑 - 另外,如果第一个 insert
失败会怎样?
编辑 - 我认为该模型可能很重要
KittehDesc json
blurb Text
color Color
size KittehSize
deriving Show
KittehPic
kittehId KittehDescId Eq
kittehPic Base64
UniqueKittehId kittehId
是的,runDB
中的所有内容都包含在交易中。如果第一次插入失败会抛出异常,代码不会到达第二次插入。
我认为这在某处有记录,但我只是跟踪代码得出这个结论:runDB
是用 defaultRunDB
, which calls into runPool
实现的,它调用 runSqlPool
,它调用 runSqlConn
,可以看到是在异常发生时处理回滚:
runSqlConn :: MonadBaseControl IO m => SqlPersistT m a -> SqlBackend -> m a
runSqlConn r conn = control $ \runInIO -> mask $ \restore -> do
let getter = getStmtConn conn
restore $ connBegin conn getter
x <- onException
(restore $ runInIO $ runReaderT r conn)
(restore $ connRollback conn getter)
restore $ connCommit conn getter
return x
我使用 Yesod 作为框架,使用 postgresql 作为数据库,并且有以下 runDB
的定义。查看 Yesod 站点上的文档,我有一种预感,以下列方式使用 runDB
将导致第一个 insert
在第二个失败时回滚。我对吗。如果没有,我该如何调用回滚?
instance YesodPersist App where
<snip>
runDB action = do
master <- getYesod
runSqlPool action $ appConnPool master
addKitteh :: Kitteh -> Handler (Either StoreError StoreResult)
addKitteh (Kitteh desc color size photo) = do
data_key <- runDB $ do
data_key <- insert (KittehDesc desc color size)
insert (KittehPic data_key photo)
...
编辑 - 另外,如果第一个 insert
失败会怎样?
编辑 - 我认为该模型可能很重要
KittehDesc json
blurb Text
color Color
size KittehSize
deriving Show
KittehPic
kittehId KittehDescId Eq
kittehPic Base64
UniqueKittehId kittehId
是的,runDB
中的所有内容都包含在交易中。如果第一次插入失败会抛出异常,代码不会到达第二次插入。
我认为这在某处有记录,但我只是跟踪代码得出这个结论:runDB
是用 defaultRunDB
, which calls into runPool
实现的,它调用 runSqlPool
,它调用 runSqlConn
,可以看到是在异常发生时处理回滚:
runSqlConn :: MonadBaseControl IO m => SqlPersistT m a -> SqlBackend -> m a
runSqlConn r conn = control $ \runInIO -> mask $ \restore -> do
let getter = getStmtConn conn
restore $ connBegin conn getter
x <- onException
(restore $ runInIO $ runReaderT r conn)
(restore $ connRollback conn getter)
restore $ connCommit conn getter
return x