title: Spring, Hibernate - many-to-many - update error
body: <p>I'm trying to use many-to-many relation in Hibernate Framework, but I have some troubles.</p>
  
  <p>I have 2 models.</p>
  
  <p>User:</p>
  
  <pre><code>@Entity
  public class User implements Serializable {
  Long id;
  String name;
  List&lt;Car&gt; cars;
  public User() {
  
  }
  public Long getId() {
      return id;
  }
  public void setId(Long id) {
      this.id = id;
  }
  public String getName() {
      return name;
  }
  public void setName(String name) {
      this.name = name;
  }
  public List&lt;Car&gt; getCars() {
      return cars;
  }
  public void setCars(List&lt;Car&gt; cars) {
      this.cars = cars;
  }
  }
  </code></pre>
  
  <p>Car:</p>
  
  <pre><code>@Entity
  public class Car implements Serializable {
  Long id;
  String mark;
  public Car() {
  
  }
  public Long getId() {
      return id;
  }
  public void setId(Long id) {
      this.id = id;
  }
  public String getMark() {
      return mark;
  }
  public void setMark(String mark) {
      this.mark = mark;
  }
  }
  </code></pre>
  
  <p>I followed by clues on this <a href="http://www.vaannila.com/hibernate/hibernate-example/hibernate-mapping-many-to-many-1.html" rel="nofollow">page</a>, so my configuration files looks like this:</p>
  
  <p>User: </p>
  
  <pre><code>&lt;hibernate-mapping&gt;
  &lt;class name="com.bontade.phone_book.mvc.spring.models.User" table="USERS"&gt;
      &lt;id name="id" type="java.lang.Long"&gt;
          &lt;column name="ID" /&gt;
          &lt;generator class="identity" /&gt;
      &lt;/id&gt;        
      &lt;property name="name" not-null="true" length="100" type="java.lang.String"&gt;
          &lt;column name="NAME" /&gt;
      &lt;/property&gt;       
      &lt;list name="cars" table="USER_CAR" cascade="all"&gt;
          &lt;key&gt;
              &lt;column name="USER_ID" /&gt;
          &lt;/key&gt;
          &lt;list-index&gt;&lt;/list-index&gt;
          &lt;many-to-many column="CAR_ID" class="com.bontade.phone_book.mvc.spring.models.Car" /&gt;
      &lt;/list&gt;        
  &lt;/class&gt;
  &lt;/hibernate-mapping&gt;
  </code></pre>
  
  <p>Car:</p>
  
  <pre><code>&lt;hibernate-mapping&gt;
  &lt;class name="com.bontade.phone_book.mvc.spring.models.Car" table="CARS"&gt;
      &lt;id name="id" type="java.lang.Long"&gt;
          &lt;column name="ID" /&gt;
          &lt;generator class="identity" /&gt;
      &lt;/id&gt;
      &lt;property name="mark"  not-null="true" length="20" type="java.lang.String"&gt;
          &lt;column name="MARK" /&gt;
      &lt;/property&gt;     
  &lt;/class&gt;
  &lt;/hibernate-mapping&gt;
  </code></pre>
  
  <p>I'm getting errors:</p>
  
  <pre><code>    Hibernate: update CARS set MARK=? where ID=?
  2011-02-23 16:32:34 org.apache.catalina.core.StandardWrapperValve invoke
  SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/PhoneBook] threw exception [Request processing failed; nested exception is org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1] with root cause
  org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
      at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
      at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
      at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90)
      at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
      at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
      at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
      at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
      at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
      at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
      at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
      at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:655)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
      at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
      at com.bontade.phone_book.mvc.spring.models.dao.implementations.CarDAOImplementation.saveCar(CarDAOImplementation.java:30)
      at com.bontade.phone_book.mvc.spring.controllers.HomePageController.handleRequestInternal(HomePageController.java:43)
      at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
      at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
      at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:244)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:558)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:379)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:259)
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:281)
      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
      at java.lang.Thread.run(Thread.java:662)
  </code></pre>
  
  <hr>
  
  <p><strong>Update</strong></p>
  
  <pre><code>public class CarAOImplementation implements CarDAO {
  
  private HibernateTemplate hibernateTemplate;
  private TransactionTemplate transactionTemplate;
  public void setSessionFactory(SessionFactory sessionFactory) {
      this.hibernateTemplate = new HibernateTemplate(sessionFactory);
  }
  public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
      this.transactionTemplate = transactionTemplate;
  }
  
  @Override
  public void saveCar(final Car car) {
      // TODO Auto-generated method stub
      this.transactionTemplate.execute(new TransactionCallback() {
  
          public Object doInTransaction(TransactionStatus transactionStatus) {
              try {
                  hibernateTemplate.saveOrUpdate(car);
              } catch (Exception e) {
                  transactionStatus.setRollbackOnly();
              }
              return null;
          }
      });
  }
  ...
  }
  </code></pre>
  
  <hr>
  
  <p><strong>Update 2</strong></p>
  
  <pre><code>Car markCar = new Car();
  markCar.setId(null);
  markCar.setMark("111");
  carDAO.saveCar(markCar);
  
  User mark = new User();
  mark.setId(null);
  mark.setName("mark");
  List a = new ArrayList&lt;Car&gt;();
  a.add(markCar);
  mark.setCars(a);
  userDAO.saveUser(mark);
  List&lt;User&gt; users = userDAO.getAll();
  System.out.println("==" + users.size() + "===");
  System.out.println(users.get(0).getCars().get(0).getMark());
  </code></pre>
  
  <p>Stack trace: </p>
  
  <pre><code>    Hibernate: select user0_.ID as ID0_, user0_.NAME as NAME0_ from USERS user0_
  ==1==
  2011-02-23 17:35:10 org.apache.catalina.core.StandardWrapperValve invoke
  SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/PhoneBook] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.bontade.phone_book.mvc.spring.models.User.cars, no session or session was closed] with root cause
  org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.bontade.phone_book.mvc.spring.models.User.cars, no session or session was closed
      at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
      at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
      at org.hibernate.collection.AbstractPersistentCollection.readElementByIndex(AbstractPersistentCollection.java:173)
      at org.hibernate.collection.PersistentList.get(PersistentList.java:293)
      at com.bontade.phone_book.mvc.spring.controllers.HomePageController.handleRequestInternal(HomePageController.java:59)
      at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
      at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
      at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:244)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:558)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:379)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:259)
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:281)
      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
      at java.lang.Thread.run(Thread.java:662)
  </code></pre>