Affects: \5.3.20 org.springframework : spring-aop 5.3.20 spring-orm 5.3.18
I have one entity Parent that holds a set of child entities, what I do is
- pulling the parent entity from DB
- add a child entity to the set (no id
value)
- call getSessionFactory().getCurrentSession().lock(entity, LockMode.OPTIMISTIC);
- then the exception get thrown
It would work and insert/update the parent and child if I call update
.
Also changing a non-collection property (String) will work with the LOCK.
only the LOCK and a collection get failed.
I don't understand the check for isDirty()
in OnLockVisitor
line 47, why do we care if the collection is dirty, we don't check that when the String is dirty.
Is there a way around it?
parent entity
@Entity
@Table(name = "tenant_users")
public class TenantUser {
@Id
@SequenceGenerator(name = "tenant_users_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tenant_users_id_seq")
@Column(name = "id")
private Long id;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "tenantUser", cascade = CascadeType.ALL, orphanRemoval = true)
@Where(clause = "is_deleted is false")
@JsonManagedReference
@OptimisticLock(excluded = true)
private Set<TenantUserBusinessUnit> businessUnits = new HashSet<>();
@Version
@Column(name = "version")
private LocalDateTime version;
}
child entity
@Entity
@Table(name = "tenant_user_business_units")
public class TenantUserBusinessUnit
@Id
@SequenceGenerator(name = "tenant_user_business_units_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tenant_user_business_units_id_seq")
@Column(name = "id")
private Long id;
@JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "id")
@ManyToOne(optional = false)
@JoinColumn(name = "tenant_user_id")
@JsonBackReference
private TenantUser tenantUser;
Exception Stack trace:
org.hibernate.HibernateException: re-associated object has dirty collection
at org.hibernate.event.internal.OnLockVisitor.processCollection(OnLockVisitor.java:48)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:104)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:65)
at org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:59)
at org.hibernate.event.internal.AbstractVisitor.process(AbstractVisitor.java:126)
at org.hibernate.event.internal.AbstractReassociateEventListener.reassociate(AbstractReassociateEventListener.java:84)
at org.hibernate.event.internal.DefaultLockEventListener.onLock(DefaultLockEventListener.java:79)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:745)
at org.hibernate.internal.SessionImpl.lock(SessionImpl.java:731)
Comment From: jhoeller
As far as I can see, there is nothing specific to Spring here. Please report this issue to the Hibernate project instead.