title: Optimistic locking with hibernate and trigger - "Strange" behaviour
body: <p>I want to use the optimistic locking feature present in hibernate. To do this I configured the mapping for my table as follows:</p>
  
  <pre><code>&lt;hibernate-mapping package="org.example.dao.entity"&gt;
      &lt;class name="org.example.dao.entity.EmployeeEntity" table="employee" dynamic-update="false"&gt;
          &lt;id name="id" column="employee_id"&gt;
              &lt;generator class="identity"/&gt;
          &lt;/id&gt;
          &lt;version name="version" column="version" type="java.lang.Integer" generated="always"/&gt;
          &lt;property name="firstName" column="first_name" type="java.lang.String"/&gt;
          &lt;set name="projects" table="employee_to_project" inverse="true"&gt;
              &lt;key column="employee_id"/&gt;
              &lt;many-to-many column="project_id" class="ProjectEntity"/&gt;
          &lt;/set&gt;
      &lt;/class&gt;
  &lt;/hibernate-mapping&gt;
  </code></pre>
  
  <p>I used generated="always" and created the following trigger in db:</p>
  
  <pre><code>CREATE OR REPLACE FUNCTION public.tab_employee_update_version()
    RETURNS trigger
    LANGUAGE plpgsql
  AS
  $body$
  BEGIN
    NEW.version = coalesce(OLD.version,0) + 1;
    RETURN NEW;
  END;
  $body$
  /
  </code></pre>
  
  <p>Then I run the following code:</p>
  
  <pre><code>public static void main(String[] args) {
          ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml");
  
          final EmployeeService employeeService = ctx.getBean("employeeService", EmployeeService.class);
  
          // SELECT
          Employee employee = employeeService.getById(1L);
  
          // UPDATE
          employeeService.update(employee);    
      }
  </code></pre>
  
  <p>and get the HibernateOptimisticLockingFailureException despite the fact that employee record was not changed by another transaction meantime:</p>
  
  <pre><code>Exception in thread "main" org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Object of class [org.example.dao.entity.EmployeeEntity] with identifier [1]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.example.dao.entity.EmployeeEntity#1]
      at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:202)
      at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:730)
      at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:592)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
      at com.sun.proxy.$Proxy15.update(Unknown Source)
      at org.example.AppMain.main(AppMain.java:25)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:606)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
  Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.example.dao.entity.EmployeeEntity#1]
      at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2541)
      at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3285)
      at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
      at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
      at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:159)
      at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
      at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
      at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
      at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
      at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1258)
      at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
      at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
      at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
      at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
      ... 14 more
  </code></pre>
  
  <p>Transaction boundaries are on service level (the EmployeeService class is marked with the @Transactional annotation). </p>
  
  <p>I debugged the code and found out, that hibernate automatically increases the version during the update:</p>
  
  <pre><code>Hibernate: select employeeen0_.employee_id as employee1_1_0_, employeeen0_.version as version2_1_0_, employeeen0_.age as age3_1_0_, employeeen0_.first_name as first_na4_1_0_, employeeen0_.last_name as last_nam5_1_0_ from employee employeeen0_ where employeeen0_.employee_id=?
  10:36:46,258 TRACE main sql.BasicBinder:81 - binding parameter [1] as [BIGINT] - [1]
  10:36:46,270 TRACE main sql.BasicExtractor:78 - extracted value ([version2_1_0_] : [INTEGER]) - [57]
  10:36:46,270 TRACE main sql.BasicExtractor:78 - extracted value ([age3_1_0_] : [INTEGER]) - [0]
  10:36:46,271 TRACE main sql.BasicExtractor:78 - extracted value ([first_na4_1_0_] : [VARCHAR]) - [Bogumil]
  10:36:46,271 TRACE main sql.BasicExtractor:78 - extracted value ([last_nam5_1_0_] : [VARCHAR]) - [Bednarek]
  10:36:46,280 TRACE main type.CollectionType:783 - Created collection wrapper: [org.example.dao.entity.EmployeeEntity.projects#1]
  
  Hibernate: select projects0_.employee_id as employee1_1_0_, projects0_.project_id as project_2_2_0_, projectent1_.project_id as project_1_3_1_, projectent1_.name as name2_3_1_ from employee_to_project projects0_ inner join project projectent1_ on projects0_.project_id=projectent1_.project_id where projects0_.employee_id=?
  10:36:46,394 TRACE main sql.BasicBinder:81 - binding parameter [1] as [BIGINT] - [1]
  10:36:46,397 TRACE main sql.BasicExtractor:78 - extracted value ([project_1_3_1_] : [BIGINT]) - [1]
  10:36:46,397 TRACE main sql.BasicExtractor:78 - extracted value ([name2_3_1_] : [VARCHAR]) - [Project1]
  10:36:46,398 TRACE main sql.BasicExtractor:78 - extracted value ([employee1_1_0_] : [BIGINT]) - [1]
  10:36:46,398 TRACE main sql.BasicExtractor:78 - extracted value ([project_2_2_0_] : [BIGINT]) - [1]
  10:36:46,399 TRACE main sql.BasicExtractor:78 - extracted value ([project_1_3_1_] : [BIGINT]) - [2]
  10:36:46,399 TRACE main sql.BasicExtractor:78 - extracted value ([name2_3_1_] : [VARCHAR]) - [Project2]
  10:36:46,400 TRACE main sql.BasicExtractor:78 - extracted value ([employee1_1_0_] : [BIGINT]) - [1]
  10:36:46,400 TRACE main sql.BasicExtractor:78 - extracted value ([project_2_2_0_] : [BIGINT]) - [2]
  
  Hibernate: update employee set age=?, first_name=?, last_name=? where employee_id=? and version=?
  10:36:46,426 TRACE main sql.BasicBinder:81 - binding parameter [1] as [INTEGER] - [0]
  10:36:46,426 TRACE main sql.BasicBinder:81 - binding parameter [2] as [VARCHAR] - [Bogumil]
  10:36:46,427 TRACE main sql.BasicBinder:81 - binding parameter [3] as [VARCHAR] - [Bednarek]
  10:36:46,427 TRACE main sql.BasicBinder:81 - binding parameter [4] as [BIGINT] - [1]
  10:36:46,427 TRACE main sql.BasicBinder:81 - binding parameter [5] as [INTEGER] - [58]
  </code></pre>
  
  <p>Additionally, I found out that if I select and update a record in the same transaction, hibernate does not increase the version and everything works fine.</p>
  
  <p>And one more observation. After removing the 'set' element from the mapping file, everything works fine:</p>
  
  <pre><code>&lt;set name="projects" table="employee_to_project" inverse="true"&gt;
      &lt;key column="employee_id"/&gt;
      &lt;many-to-many column="project_id" class="ProjectEntity"/&gt;
  &lt;/set&gt;
  </code></pre>
  
  <p><strong>Can somebody explain me, why hibernate increases the version and therefore I get the exception?</strong></p>
  
  <p>More details about my application:</p>
  
  <ul>
  <li>springframework version: 4.2.0.RELEASE</li>
  <li>hibernate version: 4.3.11.Final</li>
  <li>postgreSQL version: 9.3</li>
  </ul>