1、为了初步解决并发造成的问题,我们通常会在实体类上声明一个版本管理字段,并且引入的@version注解,这就就简单实现了乐观锁功能;
@Version
private Long version;
2、在操作表单提交时,hibernate会根据操作类型进行(如果是新增,默认会生成一个版本为0的版本号,
后面每次修改都会在现有版本后的基础上加1)对版本号进行维护。
应用场景:
如果两个人(甲,乙)同时对同实体进行修改,甲先提交,乙后提交,那么乙提交是会报错的。(因为甲已修改,乙提交的版本号比数据库中的版本号低,因此不能进行更新)。
注意事项:
运用版本控制字段需要注意,在修改时要将版本号一起提交,否则hibernate因为维护版本号时因无法参考当前版本而抛出空指针异常。
hibernate异常抛出位置:
org.hibernate.type.LongType
@SuppressWarnings({ "UnnecessaryBoxing", "UnnecessaryUnboxing" })
public Long next(Long current, SessionImplementor session) {
return Long.valueOf( current.longValue() + 1 );
}
异常信息:
严重: Servlet.service() for servlet springmvc threw exception
java.lang.NullPointerException
at org.hibernate.type.LongType.next(LongType.java:76)
at org.hibernate.type.LongType.next(LongType.java:40)
at org.hibernate.engine.Versioning.increment(Versioning.java:131)
at org.hibernate.event.def.DefaultFlushEntityEventListener.getNextVersion(DefaultFlushEntityEventListener.java:406)
at org.hibernate.event.def.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:296)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:155)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
解决方案:
在页面的隐藏域中放入版本号字段,随表单提交时一起提交。
<form:hidden path="version"/>