目前,Hibernate对PostgreSQL的for update nowait语法是不支持的,(Hibernate3.2.4),由于项目的需要,只好自己来实现。Hibernate在解析SQL文的时候,利用的是Hibernate的Dialect,我们可以通过重载org.hibernate.dialect.PostgreSQLDialect来实现对for update nowait的支持。
1.重载PostgreSQLDialect
只需要重写getForUpdateNowaitString()即可
2.修正Hibernate设定文件(hibernate.cfg.xml)
< hibernate-configuration >
< session-factory >
< property name ="connection.driver_class" > org.postgresql.Driver </ property >
< property name ="connection.url" > jdbc:postgresql:/localhost/sample </ property >
< property name ="connection.username" > guest </ property >
< property name ="connection.password" > guest </ property >
< property name ="show_sql" > true </ property >
< property name ="dialect" > test.MyPostgreSQLDialect </ property > ← 修正这里
< mapping resource ="test/Test.hbm.xml" />
</ session-factory >
</ hibernate-configuration >
3.如果利用Spring去连接Hibernate,则在Sping的applicationContext.xml文件中要做以下修正
< bean id ="sessionFactory" class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="dataSource" >
< ref local ="dataSource" />
</ property >
< property name ="configLocation" >
< value > WEB-INF/classes/koichi/hibernate.cfg.xml </ value >
</ property >
< property name ="configurationClass" >
< value > org.hibernate.cfg.AnnotationConfiguration </ value >
</ property >
< property name ="hibernateProperties" >
< props >
< prop key ="hibernate.show_sql" > true </ prop >
< prop key ="hibernate.dialect" > test.MyPostgreSQLDialect </ prop > ← 这里需要修改
</ props >
</ property >
</ bean >
3.nowait的代码实现
只需要指定LockMode.UPGRADE_NOWAIT即可。
HogeDTO dto = (HogeDTO) getHibernateTemplate().
load(HogeDTO. class , hogeid, LockMode.UPGRADE_NOWAIT);
发生Lock错误的时候,会报出以下消息:
Caused by: org.postgresql.util.PSQLException: ERROR: could not obtain lock on row in relation " hoge "
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java: 1512 )
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java: 1297 )
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java: 188 )
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java: 437 )
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java: 353 )
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java: 257 )
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java: 92 )
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java: 137 )
at org.hibernate.loader.Loader.getResultSet(Loader.java: 1676 )
at org.hibernate.loader.Loader.doQuery(Loader.java: 662 )
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java: 223 )
at org.hibernate.loader.Loader.loadEntity(Loader.java: 1782 )
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java: 93 )
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java: 81 )
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java: 2729 )
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java: 365 )
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java: 346 )
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java: 123 )
at org.hibernate.event.def.DefaultLoadEventListener.lockAndLoad(DefaultLoadEventListener.java: 272 )
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java: 90 )
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java: 809 )
at org.hibernate.impl.SessionImpl.load(SessionImpl.java: 792 )
at org.hibernate.impl.SessionImpl.load(SessionImpl.java: 787 )
at org.springframework.orm.hibernate3.HibernateTemplate$ 3 .doInHibernate(HibernateTemplate.java: 478 )
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java: 358 )
... 77 more
1.重载PostgreSQLDialect
只需要重写getForUpdateNowaitString()即可
import
org.hibernate.dialect.PostgreSQLDialect;
public class MyPostgreSQLDialect extends PostgreSQLDialect {
@Override
public String getForUpdateNowaitString() {
return " for update nowait";
}
}
public class MyPostgreSQLDialect extends PostgreSQLDialect {
@Override
public String getForUpdateNowaitString() {
return " for update nowait";
}
}
2.修正Hibernate设定文件(hibernate.cfg.xml)
< hibernate-configuration >
< session-factory >
< property name ="connection.driver_class" > org.postgresql.Driver </ property >
< property name ="connection.url" > jdbc:postgresql:/localhost/sample </ property >
< property name ="connection.username" > guest </ property >
< property name ="connection.password" > guest </ property >
< property name ="show_sql" > true </ property >
< property name ="dialect" > test.MyPostgreSQLDialect </ property > ← 修正这里
< mapping resource ="test/Test.hbm.xml" />
</ session-factory >
</ hibernate-configuration >
3.如果利用Spring去连接Hibernate,则在Sping的applicationContext.xml文件中要做以下修正
< bean id ="sessionFactory" class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="dataSource" >
< ref local ="dataSource" />
</ property >
< property name ="configLocation" >
< value > WEB-INF/classes/koichi/hibernate.cfg.xml </ value >
</ property >
< property name ="configurationClass" >
< value > org.hibernate.cfg.AnnotationConfiguration </ value >
</ property >
< property name ="hibernateProperties" >
< props >
< prop key ="hibernate.show_sql" > true </ prop >
< prop key ="hibernate.dialect" > test.MyPostgreSQLDialect </ prop > ← 这里需要修改
</ props >
</ property >
</ bean >
3.nowait的代码实现
只需要指定LockMode.UPGRADE_NOWAIT即可。
HogeDTO dto = (HogeDTO) getHibernateTemplate().
load(HogeDTO. class , hogeid, LockMode.UPGRADE_NOWAIT);
发生Lock错误的时候,会报出以下消息:
Caused by: org.postgresql.util.PSQLException: ERROR: could not obtain lock on row in relation " hoge "
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java: 1512 )
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java: 1297 )
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java: 188 )
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java: 437 )
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java: 353 )
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java: 257 )
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java: 92 )
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java: 137 )
at org.hibernate.loader.Loader.getResultSet(Loader.java: 1676 )
at org.hibernate.loader.Loader.doQuery(Loader.java: 662 )
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java: 223 )
at org.hibernate.loader.Loader.loadEntity(Loader.java: 1782 )
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java: 93 )
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java: 81 )
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java: 2729 )
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java: 365 )
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java: 346 )
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java: 123 )
at org.hibernate.event.def.DefaultLoadEventListener.lockAndLoad(DefaultLoadEventListener.java: 272 )
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java: 90 )
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java: 809 )
at org.hibernate.impl.SessionImpl.load(SessionImpl.java: 792 )
at org.hibernate.impl.SessionImpl.load(SessionImpl.java: 787 )
at org.springframework.orm.hibernate3.HibernateTemplate$ 3 .doInHibernate(HibernateTemplate.java: 478 )
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java: 358 )
... 77 more