gpt4 book ai didi

java - 如何为多个并发事务请求正确处理 JPA Object OptimisticLockException?

转载 作者:搜寻专家 更新时间:2023-10-30 21:21:17 26 4
gpt4 key购买 nike

所以,我在做一个简单的 Spring MVC + JPA (hibernate) 项目,其中有用户可以发布帖子并在他们的 friend 帖子上发表评论(有点像一个小型社交网络)。我对使用 JPA Hibernate 还是比较陌生。因此,当我尝试从浏览器进行测试时,在处理先前的请求时非常快速地发送多个任务(包含事务)的多个请求 2-3 次时,我得到一个 OptimisticLockException 。这是堆栈跟踪..

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)

现在,我该如何解决这个问题?当多个事务请求同时发生时,如何正确处理此 ObjectOptimisticLockException?有什么我应该遵循的好模式吗?我需要使用某种悲观锁定机制吗?

这是我目前正在使用的 DAO。提前致谢。 :)

@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<Post> 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<Post> getAllPosts() {

return entityManager.createQuery("SELECT p FROM Post AS p ORDER BY p.created DESC", Post.class).getResultList();
}

@Override
public List<Post> getNewsFeedPostsWithComments(int userId) {
List<Post> 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<Post> getFriendsPost(User user) {
List<Post> friendsPosts = new ArrayList<Post>();

for (User u : user.getFriends()) {
friendsPosts.addAll(getUserPosts(u.getId()));
}

return friendsPosts;
}


@Override
public List<Post> getUserPosts(int userId) {
TypedQuery<Post> 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<Post> getUserPostsWithComments(int userId) {
List<Post> 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<Post> query) {
query.setMaxResults(1);
List<Post> list = query.getResultList();
if (list.isEmpty()) {
return null;
}
return list.get(0);
}

最佳答案

JPA OptimisticLockException 阻止了 lost updates ,你不应该忽略它。

您可以简单地在通用异常处理程序中捕获它,并将用户重定向到当前正在执行的工作流的起点,表明该流必须重新启动,因为它使用的是陈旧数据。

但是,如果您的应用程序要求不需要防止丢失更新异常,那么您可以简单地从您的实体中删除 @Version 注释,从而破坏可序列化性。

现在,您可能会认为 auto-retry针对新的实体数据库快照将解决问题,但您最终会遇到相同的乐观锁定异常,因为加载时版本仍然低于数据库中的当前实体版本。

此外,您还可以使用悲观锁定(例如 PESSIMISTIC_WRITEPESSIMISTIC_READ),这样一旦获得行级锁,其他事务就无法修改锁定的记录。

关于java - 如何为多个并发事务请求正确处理 JPA Object OptimisticLockException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29574859/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com