目前,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";
}
}









2.修正Hibernate设定文件(hibernate.cfg.xml)












3.如果利用Spring去连接Hibernate,则在Sping的applicationContext.xml文件中要做以下修正


















3.nowait的代码实现
只需要指定LockMode.UPGRADE_NOWAIT即可。


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