I've been struggling to get a custom timestamp-based type to work as a UserVersionType. My type is based on HibernateUTC.java posted on the wiki here
http://www.hibernate.org/100.html. I'll be updating that node "Real Soon Now" with my modified code to make the UserType usable as a UserVersionType.
I am running the code inside JBoss 5, Sun Java 1.6.0.12 on Fedora Core 10. I was repeatedly getting an error saying
Code:
2009-03-20 00:01:20,845 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] (WorkerThread#0[127.0.0.1:53231]) Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect):
[fvis.drpg.entity.Security#15]
The column is database generated via a trigger on insert/update.
After staring at the problem for a while, RTFM, changing the version property definition about every way I could think of, it finally occurred to me that Timestamps in PostgreSQL (and Oracle) are more precise than milliseconds. Timestamp
does have a getNanos(), so I had expected this wouldn't be an issue, but....
I changed the PostgreSQL column definitions to timestamp(3) which specified 3 digit fractional precision on the seconds (i.e., milliseconds). Problem gone.
I'm not really sure where to report this as a problem. Is this a Hibernate problem? A PostgreSQL JDBC problem? A JBoss problem?
Hibernate version: It's whatever is bundled with JBoss 5 which I
think is 3.3.1.
Mapping documents:hibernate.cfg.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="java:hibernate/SessionFactory">
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.hbm2ddl.auto">verify</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.default_schema">drpg</property>
</session-factory>
</hibernate-configuration>
Security.hbm.xml
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="fvis.drpg.entity.Security">
<id name="securityId" column="id" type="long" unsaved-value="null">
<generator class="sequence">
<param name="sequence">security_id_seq</param>
</generator>
</id>
<natural-id>
<property name="primaryIdentifier"
column="primary_identifier"
type="string"/>
</natural-id>
<version name="activeOn"
column="active_on"
type="fvis.util.HibernateUTC$TimestampType"
generated="always"
insert="false"
unsaved-value="null"/>
<property name="identifierTypeCode"
column="identifier_type_code"
type="string"/>
<property name="securityTypeCode"
column="security_type_code"
type="string"/>
<property name="securityName"
column="issue_name"
type="string"/>
<property name="issuerName"
column="issuer_name"
type="string"/>
<property name="industryName"
column="industry_name"
type="string"/>
<property name="exchangeCode"
column="exchange_code"
type="string"/>
<property name="micCode"
column="mic_code"
type="string"/>
<property name="defaultSectorCode"
column="def_sector_code"
type="string"/>
<property name="icb4SectorCode"
column="icb4_code"
type="string"/>
<property name="defaultGdrSecurityId"
column="def_gdr_security_id"
type="long"/>
<property name="live"
column="is_live"
type="yes_no" length="1"/>
<property name="sharesOutstanding"
column="shares_outstanding"
type="long"/>
<property name="lastPriceModifiedTime"
column="last_price_modified_time"
type="fvis.util.HibernateUTC$TimestampType" />
<property name="lastPriceTime"
column="last_price_time"
type="fvis.util.HibernateUTC$TimestampType" />
<property name="lastPriceValidatedTime"
column="last_price_validated_time"
type="fvis.util.HibernateUTC$TimestampType" />
<property name="activeUntil"
column="active_until"
type="fvis.util.HibernateUTC$TimestampType" />
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():I don't think this is applicable for JBoss....
Full stack trace of any exception that occurs:From the JBoss server log...
Code:
2009-03-20 00:50:59,664 DEBUG [org.hibernate.jdbc.AbstractBatcher] (WorkerThread#0[127.0.0.1:37840]) about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2009-03-20 00:50:59,664 DEBUG [org.hibernate.jdbc.ConnectionManager] (WorkerThread#0[127.0.0.1:37840]) skipping aggressive-release due to flush cycle
2009-03-20 00:50:59,664 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] (WorkerThread#0[127.0.0.1:37840]) Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [fvis.drpg.entity.Security#1]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1792)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2435)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:64)
at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:996)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1141)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:88)
at fvis.drpg.SecurityBean.findByPrimaryIdentifier(SecurityBean.java:95)
at fvis.drpg.SecurityBean.validate(SecurityBean.java:73)
at fvis.drpg.SecurityBean.validate(SecurityBean.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.jboss.aop.joinpoint.MethodInvocation.invokeTarget(MethodInvocation.java:122)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111)
at org.jboss.ejb3.EJBContainerInvocationWrapper.invokeNext(EJBContainerInvocationWrapper.java:69)
at org.jboss.ejb3.interceptors.aop.InterceptorSequencer.invoke(InterceptorSequencer.java:73)
at org.jboss.ejb3.interceptors.aop.InterceptorSequencer.aroundInvoke(InterceptorSequencer.java:59)
at sun.reflect.GeneratedMethodAccessor327.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.jboss.aop.advice.PerJoinpointAdvice.invoke(PerJoinpointAdvice.java:174)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor.fillMethod(InvocationContextInterceptor.java:72)
at org.jboss.aop.advice.org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor_z_fillMethod_16236333.invoke(InvocationContextInterceptor_z_fillMethod_16236333.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor.setup(InvocationContextInterceptor.java:88)
at org.jboss.aop.advice.org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor_z_setup_16236333.invoke(InvocationContextInterceptor_z_setup_16236333.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:56)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:68)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:190)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.security.RoleBasedAuthorizationInterceptorv2.invoke(RoleBasedAuthorizationInterceptorv2.java:201)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptorv2.invoke(Ejb3AuthenticationInterceptorv2.java:186)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:41)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.BlockContainerShutdownInterceptor.invoke(BlockContainerShutdownInterceptor.java:67)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor.invoke(CurrentInvocationInterceptor.java:67)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:487)
at org.jboss.ejb3.session.InvokableContextClassProxyHack._dynamicInvoke(InvokableContextClassProxyHack.java:53)
at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:91)
at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:908)
at org.jboss.remoting.transport.socket.ServerThread.completeInvocation(ServerThread.java:742)
at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:695)
at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:522)
at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:230)
2009-03-20 00:50:59,666 DEBUG [org.hibernate.jdbc.ConnectionManager] (WorkerThread#0[127.0.0.1:37840]) aggressively releasing JDBC connection
2009-03-20 00:50:59,666 DEBUG [org.hibernate.jdbc.ConnectionManager] (WorkerThread#0[127.0.0.1:37840]) releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
2009-03-20 00:50:59,666 DEBUG [org.hibernate.ejb.AbstractEntityManagerImpl] (WorkerThread#0[127.0.0.1:37840]) mark transaction for rollback
2009-03-20 00:50:59,670 DEBUG [org.jboss.jpa.deployment.ManagedEntityManagerFactory] (WorkerThread#0[127.0.0.1:37840]) ************** closing entity managersession **************
Name and version of the database you are using:Code:
256 roland> rpm -q postgresql-server
postgresql-server-8.3.6-1.fc10.i386
257 roland> rpm -q postgresql-jdbc
postgresql-jdbc-8.3.603-1.1.fc10.i386
The generated SQL (show_sql=true):Code:
2009-03-20 00:50:59,661 DEBUG [org.hibernate.SQL] (WorkerThread#0[127.0.0.1:37840]) update drpg.Security set identifier_type_code=?, security_type_code=?, issue_name=?, issuer_name=?, industry_name=?, exchange_code=?, mic_code=?, def_sector_code=?, icb4_code=?, def_gdr_security_id=?, is_live=?, shares_outstanding=?, last_price_modified_time=?, last_price_time=?, last_price_validated_time=?, active_until=? where id=? and active_on=?
Debug level Hibernate log excerpt:Not sure how to generate this or if it is needed in this case.
[/code]