gpt4 book ai didi

java - JPA:PersistenceException,无法更新

转载 作者:行者123 更新时间:2023-11-29 13:41:57 27 4
gpt4 key购买 nike

我正在使用 Play Framework 1.2.5 和 Java,但这更多是一个 JPA 问题。

在我的项目中,我经常通过电子邮件搜索用户,因此我创建了以下方法:

public static User getUserByEmail(String email) {
User user = User.find("email = ?", email).first();
return user;
}

我通过各种方法这样调用它:

User user = User.getUserByEmail("test@email.com");

当我尝试像这样修改用户字段时:

User user = User.getUserByEmail("kospol@test.com");
user.name = "kospol";
user.save();

我经常遇到以下异常,导致完全卡住:

Execution exception (In /app/controllers/*******.java around line 46)
PersistenceException occured : update User set activated=?, ... registered=?, registeredFrom=?, version=? where id=? and version=?


play.exceptions.JavaExecutionException: update User set activated=?, ... registered=?, registeredFrom=?, version=? where id=? and version=?
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:237)
at Invocation.HTTP Request(Play!)
Caused by: javax.persistence.PersistenceException: update User set activated=?, ... registered=?, registeredFrom=?, version=? where id=? and version=?
at play.db.jpa.JPABase._save(JPABase.java:44)
at play.db.jpa.GenericModel.save(GenericModel.java:204)
at controllers.PushService.register(PushService.java:46)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:557)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:508)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:484)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:479)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:161)
... 1 more
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not update: [models.User#3606]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1389)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1317)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1323)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:965)
at play.db.jpa.JPABase._save(JPABase.java:41)
... 8 more
Caused by: org.hibernate.exception.GenericJDBCException: could not update: [models.User#3606]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2613)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2495)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2822)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:113)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:185)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:345)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:962)
... 9 more
Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2683)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2144)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2444)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2362)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2347)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2595)
... 19 more

我已将 @Version 注释添加到模型中。看来问题是超过锁定等待超时。我怎样才能避免这种情况?

我尝试使用 .merge() 方法,但没有结果,我正在考虑删除 getUserByEmail 方法并直接获取模型。

最佳答案

免责声明:如果没有整个项目,要回答您的问题并不容易,但这里有两个需要调查的潜在问题。

我非常确定问题不是由方法 getUserByEmail 本身引起的。 (特别是因为有时它有效,有时无效)。

问题是由另一个非常繁重的查询引起的,它锁定了用户表(或者可能只是您搜索的行)很长时间(超过了等待超时) )。

因此,调查繁重的查询(一种方法是记录所有 SQL 查询并查看出现异常时正在运行的查询)。

另一个选项是死锁(如果您没有看到任何长查询):这是一个典型的场景。

线程1需要锁定表User和表B。线程2需要锁定表B和表User。

时间 0:

  • 线程 1 接收表 User 的锁
  • 线程 2 接收表 B 上的锁

时间 1:

  • 线程 1 阻塞并等待表 B 上的锁
  • 线程 2 阻塞并等待表 User 上的锁

时间 2:

  • 某个线程发生wait锁超时,释放锁并抛出异常。

时间 3:

  • 另一个线程最终收到所需的锁并执行其查询。

关于java - JPA:PersistenceException,无法更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17968229/

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