2011-06-16 39 views
1

我正在使用Wicket和自定义的PageAuthorizationStrategy访问数据库以获取有关当前用户的信息,从而访问他的访问权限。每个请求都被Spring Open-Session-In-View过滤器打包以打开/关闭Hibernate会话。检票,身份验证和事务划分

这对读取数据库非常有效。无论何时需要写操作,我都会调用使用Spring的基于注释的事务处理的服务层。这也适用,但我认为这是一个特定的错误的原因:当一个对象在请求A中进行身份验证期间加载,然后在另一个请求B中进行修改,然后切换到请求A中的服务层时,服务层正在处理错误的值,因为Hibernate和底层数据库都不能确保隔离。由于我一直在努力与数据库/交易理论的具体细节,请纠正我,如果这个假设已经是错误的。

我的解决方案的第一个想法是在写入事务启动后刷新为加载身份验证的对象。尽管当由服务修改的对象同时需要认证时,这会引起问题。当Wicket使用表单中的变化数据填充对象并在提交方法中将其传递给服务时(例如),就会发生这种情况。

所以很可能,这样做的正确方法是确保身份验证代码已被包装在与可能在同一请求期间执行的任何写入代码相同的事务中。

我该如何解决这个Wicket中的“正确方法”?

编辑:这个问题变得更加的问题,因为我意识到,当事务服务方法在引发异常后回滚时,视图层会导致LazyInitializationException。显然,Spring的TransactionManager会清除会话和/或Hibernate/Spring深处的其他内容,因为我可以从数据库重新加载对象,但试图加载包含在该对象中的集合导致所述异常。任何想法如何去做这件事?如果有一种使用“每次请求一次处理”的优雅方式,我想这一切都将得到解决。

回答

1

这不是一个问题检票补偿的变化,但DB/Hibernate的问题。对于乐观和悲观策略,Hibernate有support

optimistic approach包括向实体添加一个version字段,该字段在刷新更新时将进行验证,如果该记录已被某人修改,则会导致异常。

pessimistic approach使用数据库支持锁定记录,避免并发修改。

两者都有优点和缺点,并且都将要求您主动使用相应的功能和代码,以使其工作(没有魔法灰尘)。

乐观主义者将不得不在任何地方处理异常。

悲观者将不得不处理争用和可扩展性问题。

乐观主义者可能不得不改变模式结构和/或领域模型来处理某些情况。

悲观主义者在处理该表的更新时必须经常担心锁定(您忘记锁定在一个地方,而您刚刚创建了heisenbug)。

NoSQL人会告诉他们完全放弃关系数据库,并且没有模式,事务和一致性(顺便提一下,在大多数情况下是愚蠢的),他们生活得很开心。

1

我不知道这是即使在检票“正道”的问题时,我会尝试在服务/ DAO层来解决这个问题,有喜欢的一些可能性:

  • 不使用OSIV模式获得“实时”所需的信息,当在表格上使用时,OSIV发光显示项目信息而不需要查询数据库
  • 将编辑/更改的属性附加到对象上次更改的时间戳,任何写操作之前,你可以检查时间戳和警告/从“未来”