我通过graphql API向SPA前端提供实体。前端可以获取实体,然后更新它们。
我想实施OCC。我可以使用sqlalchemy版本计数器实现这一点吗?
我天真的方法行不通:
class Entity(Base):
__tablename__ = 'entity'
id = Column(postgresql.UUID(as_uuid=True), primary_key=True, server_default=text('gen_random_uuid()'))
version = Column(Integer, nullable=False)
name = Column(String, nullable=False)
__mapper_args__ = {
# enable optimistic locking
"version_id_col": version
}
def mutate(
root,
info,
id,
version: int,
name: str,
) -> 'UpdateEntity':
entity = EntityModel.query.get(id)
entity.version = version
entity.name = name
try:
get_db_session().commit()
return UpdateEntity(entity)
except StaleDataError as e:
raise Exception(
"Updating the entity was not successful since the entity was changed in the meantime. Please refresh.")
这段代码导致一个包含版本检查的SQLUPDATE语句,但它不检查通过API传递的版本,而是检查加载了实体的版本:
INFO:sqlalchemy.engine.base.Engine:UPDATE entity SET version=%s, name=%s WHERE entity.id = %s AND entity.version = %s
INFO 2021-01-12 16:29:48,150 base.py:1236] (3, 'test', UUID('f9a13067-ffba-46e5-a5de-f395819d9957'), 2)
因此,基本上,这会导致版本字段更新,但版本检查在不应该更新的时候会成功。
如何针对通过API传入的版本进行版本检查?
我现在通过将版本字段更新为已提交的值来实现它。
代替
entity.version = version
如果我使用
from sqlalchemy.orm.attributes import set_committed_value
set_committed_value(entity, 'version', version)
然后,sqlalchemy按照预期检查版本。