我正在使用Wicket和一个自定义的PageAuthorizationStrategy,它访问数据库以获取有关当前用户的信息,从而访问他的访问权限。每个请求都由Spring Open-Session-In-View过滤器打包,以打开/关闭Hibernate会话。
这非常适合读取数据库的访问权限。每当需要编写操作时,我会调用使用Spring基于注释的事务处理的服务层。这也有用但我认为它是导致特定错误的原因:当在请求A中的身份验证期间加载对象,然后在另一个请求B中修改然后切换到请求A中的服务层时,服务层正在使用错误的值,因为Hibernate和底层数据库都不能确保隔离。由于我总是在数据库/交易理论的具体细节上苦苦挣扎,如果这个假设已经错误,请纠正我。
我对解决方案的第一个想法是在写入事务开始后立即刷新加载用于身份验证的对象。但是,当服务要修改的对象同时进行身份验证时,这会导致问题。当Wicket使用表单中的已更改数据填充对象并以提交方法(例如)传递给服务时,尤其会发生这种情况。
因此,正确的做法是确保身份验证代码已经包含在与同一请求中可能执行的任何编写代码相同的事务中。
我怎样才能在Wicket中找到“正确的方法”?
编辑:这个问题变得更加严重,因为我意识到当抛出异常后转发的服务方法回滚时,视图层会导致LazyInitializationException。显然,Spring的TransactionManager清除会话和/或Hibernate / Spring深处的其他东西出错了,因为我可以从数据库重新加载一个对象但是试图加载该对象中包含的集合会导致所述异常。任何想法如何去做?我想如果有一种优雅的方式来使用“每个请求一个事务”,那么这一切都将得到解决。
答案 0 :(得分:1)
我不确定这是否是Wicket中“正确方法”的问题,我会尝试在服务/ dao层解决这个问题,有一些可能性,如:
答案 1 :(得分:1)
这不是Wicket问题,而是DB / Hibernate问题。对于乐观和悲观策略,Hibernate都有support。
optimistic approach包括向实体添加version
字段,在刷新更新时会对其进行验证,如果记录已被某人修改,则会导致异常。
pessimistic approach使用数据库支持来锁定记录,避免并发修改。
两者都有利弊,两者都需要你积极使用这些功能和代码才能使它工作(没有魔法尘埃)。
乐观主义者必须处理可能出现的各种异常。
悲观主义者将不得不处理争用和可扩展性问题。
乐观主义者可能必须更改架构结构和/或域模型以处理某些情况。
悲观主义者在处理该表的更新时必须始终担心锁定(您忘记锁定在一个地方,而您刚刚创建了heisenbug)。
并且NoSQL人员会告诉他们完全删除关系数据库,并且没有模式,事务和一致性(在大多数情况下在某些情况下是愚蠢的,顺便说一句),幸福地生活。