title: How to handle JPA ObjectOptimisticLockException properly for multiple simultaneous transaction requests?
body: <p>So, I was working on a simple Spring MVC + JPA (hibernate) project where there are Users who can makes Posts and make Comments on their friends Posts (somewhat like a small social network) . I am still relatively new using JPA Hibernate. So, when I try to test from browser sending multiple requests for some task ( containing transactions) very quickly 2-3 times while a previous request is being processed I get an OptimisticLockException . Here 's the stack trace ..</p>
  
  <pre><code>org.springframework.web.util.NestedServletException: Request processing   failed; nested exception is org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class [org.facebookjpa.persistance.entity.Post] with identifier [19]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [org.facebookjpa.persistance.entity.Post#19]
  org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
  org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
  javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
  org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
  javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
  </code></pre>
  
  <p>Now, how do i fix this? How do i handle this ObjectOptimisticLockException properly when multiple transaction requests occurs simultaneously ? Is there any good patten that i should follow ? Do i need to use some sort of Pessimistic Locking mechanism ? </p>
  
  <p>Here's the DAO that i am currently using .. Thanks in advance . :) </p>
  
  <pre><code>@Repository
  @Transactional
  public class PostDAOImpl implements PostDAO {
  
  @Autowired
  UserDAO userDAO;
  
  @Autowired
  CommentDAO commentDAO;
  
  @Autowired
  LikeDAO likeDAO;
  
  @PersistenceContext
  private EntityManager entityManager;
  
  public PostDAOImpl() {
  
  }
  
  @Override
  public boolean insertPost(Post post) {
      entityManager.persist(post);
      return true;
  }
  
  @Override
  public boolean updatePost(Post post) {
      entityManager.merge(post);
      return true;
  }
  
  @Override
  public Post getPost(int postId) {
      TypedQuery&lt;Post&gt; query = entityManager.createQuery("SELECT p FROM Post AS p WHERE p.id=:postId", Post.class);
      query.setParameter("postId", postId);
      return getSingleResultOrNull(query);
  }
  
  @Override
  public List&lt;Post&gt; getAllPosts() {
  
      return entityManager.createQuery("SELECT p FROM Post AS p ORDER BY p.created DESC", Post.class).getResultList();
  }
  
  @Override
    public List&lt;Post&gt; getNewsFeedPostsWithComments(int userId) {
      List&lt;Post&gt; newsFeedPosts = getUserPosts(userId);
      newsFeedPosts.addAll(getFriendsPost(userDAO.getUser(userId)));
  
      for (Post post : newsFeedPosts) {
          post.setComments(commentDAO.getPostComments(post.getId()));
          post.setLikes(likeDAO.getPostLikes(post.getId()));
      }
  
      return newsFeedPosts;
  }
  
  public List&lt;Post&gt; getFriendsPost(User user) {
      List&lt;Post&gt; friendsPosts = new ArrayList&lt;Post&gt;();
  
      for (User u : user.getFriends()) {
          friendsPosts.addAll(getUserPosts(u.getId()));
      }
  
      return friendsPosts;
  }
  
  
  @Override
  public List&lt;Post&gt; getUserPosts(int userId) {
      TypedQuery&lt;Post&gt; query = entityManager.createQuery("SELECT p FROM Post AS p WHERE p.user.id = :userId ORDER BY p.created DESC", Post.class);
      query.setParameter("userId", userId);
      return query.getResultList();
  }
  
  @Override
  public List&lt;Post&gt; getUserPostsWithComments(int userId) {
      List&lt;Post&gt; userPostsWithComments = getUserPosts(userId);
  
      for (Post post : userPostsWithComments) {
          post.setComments(commentDAO.getPostComments(post.getId()));
          post.setLikes(likeDAO.getPostLikes(post.getId()));
      }
  
      return userPostsWithComments;
  }
  
  @Override
  public boolean removePost(Post post) {
      entityManager.remove(post);
      return true;
  }
  
  @Override
  public boolean removePost(int postId) {
      entityManager.remove(getPost(postId));
      return true;
  }
  
  
  private Post getSingleResultOrNull(TypedQuery&lt;Post&gt; query) {
      query.setMaxResults(1);
      List&lt;Post&gt; list = query.getResultList();
      if (list.isEmpty()) {
          return null;
      }
      return list.get(0);
  }
  </code></pre>
  
  <p>}</p>