当我使用 Spring 中的HibernateTemplate访问mysql数据库时遇到问题。它在单线程环境中工作正常,但它总是抛出关于 多线程中的OptimisticLocking的异常。
详细异常如下图
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [com.cmcol.Mapping.Resource_Movie] with identifier [2357708]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.cmcol.Mapping.Resource_Movie#2357708]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:683)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
at com.cmcol.Atom.DatabaseTemplate.storeResource(DatabaseTemplate.java:55)
at com.cmcol.XMLCatcher.DoubanMovieInfoCatcherXML.Storage(DoubanMovieInfoCatcherXML.java:191)
at com.cmcol.XMLCatcher.DoubanMovieInfoCatcherXML.Controller(DoubanMovieInfoCatcherXML.java:79)
at com.cmcol.Atom.CatcherProcess.MovieCatcher(CatcherProcess.java:69)
at com.cmcol.Atom.CatcherProcess.run(CatcherProcess.java:52)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.cmcol.Mapping.Resource_Movie#2357708]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1950)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2594)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2494)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2821)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:113)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:185)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:390)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:407)
... 10 more
Mapping.Resource_Movie 源代码显示为
@Entity
@Table(name = "resource_movie")
public class Resource_Movie implements MappingResourceInterface {
@Version
private int version;
@Id
@Column(name = "movieID")
private Integer movieID;
@Column(name = "id")
private Integer id;
@Column(name = "[title]")
@Basic(fetch = FetchType.LAZY)
private String title;
//get and set functions}
我创建了一个名为com.cmcol.Atom.DatabaseTemplate的类,其中包含来自 Spring autowired 的HibernateTemplate的一个实例。它的代码是
@Repository
public class DatabaseTemplate {
@Autowired
@Qualifier("resourceTemplate")
private HibernateTemplate resourceTemplate;
public synchronized boolean storeResource(Resource_Movie entity) {
resourceTemplate.saveOrUpdate(entity);
return true;
} }
DatabaseTemplate 也会自动装配到其他实例中,但是在多线程环境中会遇到 OptimisticLocking 的问题。
是什么原因以及如何解决?