I got a Java JPA application where I have a Websocket controller to handle my websocket requests. Updating an entity was working just fine in other functions but when I try to update a BordRowItem
entity it does work when I'm setting a boolean in the BordRowItemTask
on true/false but not when I try to update the description
of the BordRowItem
. Both updating the BordRowItemTask
and the description
are in the same method. The method is called with a single purpose: not both BordRowItemTask
and the description
will be updated at the same time. However, I'm getting a PessimisticLockingFailureException
Code where I update the task entity:
Optional<BordRowItem> optionalBordRowItem = bordRowItemRepository.findById(object.getInt("id"));
BordRowItem item = optionalBordRowItem.get();
JSONObject task = object.getJSONObject("task");
List<BordRowItemTask> tasks = item.getTasks();
Hibernate.initialize(tasks);
if(task.has("id")) {
Optional<BordRowItemTask> optionalBordRowItemTask = bordRowItemTaskRepository.findById(task.getInt("id"));
if(optionalBordRowItemTask.isPresent()) {
for(BordRowItemTask bordRowItemTask : tasks) {
if(bordRowItemTask.getId() == optionalBordRowItemTask.get().getId()) {
bordRowItemTask.setDescription(task.getString("description"));
bordRowItemTask.setChecked(task.getBoolean("checked"));
BordRowItemEvent event = new BordRowItemEvent("i have '" + bordRowItemTask.getDescription() + (bordRowItemTask.isChecked() ? "' changed" : "' not"));
event.setBordRowItem(item);
events.add(event);
bordRowItemTaskRepository.save(bordRowItemTask);
entityManager.flush();
break;
}
}
}
}
Code where I update the description:
String msg = (item.getDescription() != null && !item.getDescription().isEmpty()) ? " van '" + item.getDescription() + "'" : "";
BordRowItemEvent event = new BordRowItemEvent("i changed a thing" + msg + " to '" + object.getString("description") + "'");
event.setBordRowItem(item);
events.add(event);
item.setDescription(object.getString("description"));
End of the websocket method to save the item:
bordRowItemRepository.save(item);
entityManager.flush();
entityManager.getTransaction().commit();
entityManager.close();
BordRowItem:
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import org.springframework.lang.Nullable;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity
@Table(name = "bord_row_items")
public class BordRowItem
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@CreationTimestamp
@JsonIgnore
private Date created_at;
@UpdateTimestamp
@JsonIgnore
private Date updated_at;
@JsonIgnore
private Date deleted_at;
@NotNull
private Integer created_by;
@NotNull
private String title;
@Column(name = "story_points")
private Integer storyPoints;
private Date expiry_date;
private String description;
@OneToMany(mappedBy = "bordRowItem")
private List<BordRowItemTask> tasks;
@OneToMany(mappedBy = "bordRowItem")
private List<BordRowItemEvent> events;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinTable(
name = "bord_row_item_labels",
joinColumns = @JoinColumn(name = "bord_row_item_id"),
inverseJoinColumns = @JoinColumn(name = "bord_row_label_id"))
private List<BordRowLabel> labels;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "bord_row_id")
@JsonIgnore
private BordRow bordRow;
public BordRowItem() {
this.tasks = new ArrayList<>();
this.labels = new ArrayList<>();
this.events = new ArrayList<>();
}
public BordRowItem(String title) {
this.title = title;
this.tasks = new ArrayList<>();
this.labels = new ArrayList<>();
this.events = new ArrayList<>();
}
//getters and setters
}
Error:
org.springframework.dao.PessimisticLockingFailureException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.PessimisticLockException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:292) ~[spring-orm-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:254) ~[spring-orm-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:537) ~[spring-orm-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:744) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:712) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:619) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:372) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178) ~[spring-data-jpa-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at com.sun.proxy.$Proxy130.save(Unknown Source) ~[na:na]
at com.myproject.project.project.controller.WebSocketController.updateBordRowItem(WebSocketController.java:323) ~[main/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_221]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_221]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_221]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_221]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171) ~[spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) ~[spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:565) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:511) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:94) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:520) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:454) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:144) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_221]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_221]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_221]
Caused by: org.hibernate.PessimisticLockException: could not execute statement
at org.hibernate.dialect.MySQLDialect$3.convert(MySQLDialect.java:536) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3392) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3265) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3666) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:149) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_221]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:349) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1358) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:436) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3235) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2403) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:533) ~[spring-orm-5.2.0.RELEASE.jar:5.2.0.RELEASE]
... 30 common frames omitted
Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:123) ~[mysql-connector-java-8.0.18.jar:8.0.18]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.18.jar:8.0.18]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.18.jar:8.0.18]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) ~[mysql-connector-java-8.0.18.jar:8.0.18]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092) ~[mysql-connector-java-8.0.18.jar:8.0.18]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040) ~[mysql-connector-java-8.0.18.jar:8.0.18]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347) ~[mysql-connector-java-8.0.18.jar:8.0.18]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025) ~[mysql-connector-java-8.0.18.jar:8.0.18]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-3.4.1.jar:na]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) ~[HikariCP-3.4.1.jar:na]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
... 51 common frames omitted