I recently updated my project from Hibernate 5.4 to Hibernate 6.6, and now I’m encountering an error that wasn’t happening before.
I have two entities: ProductEntity
and ProductProfitabilityEntity
, which are part of the same model and share the same ID. These entities are replicated from another microservice, meaning they arrive fully populated, including their IDs. Because of this, there is no @GeneratedValue annotation on their ID fields, as the IDs are assigned externally and must remain unchanged.
ProductEntity has a one-to-one relationship with ProductProfitabilityEntity. ProductProfitabilityEntity uses @MapsId, ensuring its ID is always the same as the ProductEntity ID. Both entities reference each other:
- ProductEntity has a profitability field referencing ProductProfitabilityEntity.
- ProductProfitabilityEntity has a product field referencing ProductEntity.
ProductEntity:
package br.triersistemas.cloud.platform.desktop.entity.product;
import br.triersistemas.cloud.database.entity.AuditingExternalEntity;
import br.triersistemas.cloud.platform.desktop.entity.productprofitability.ProductProfitabilityEntity;
import jakarta.persistence.*;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import java.util.UUID;
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@Entity
@Table(name = "product")
public class ProductEntity extends AuditingExternalEntity {
@Getter
@Setter
@Id
@Column(name = "id")
private UUID id;
@Getter
@Setter
@Column(name = "product_code")
private Long productCode;
// Contains one ProductProfitabilityEntity
@Valid
@OneToOne(mappedBy = "product", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private ProductProfitabilityEntity profitability;
}
ProductProfitabilityEntity:
package br.triersistemas.cloud.platform.desktop.entity.productprofitability;
import br.triersistemas.cloud.database.entity.AuditingEntity;
import br.triersistemas.cloud.platform.desktop.entity.product.ProductEntity;
import jakarta.persistence.*;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import java.util.UUID;
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@Entity
@Table(name = "product_profitability")
public class ProductProfitabilityEntity extends AuditingEntity {
@NotNull(message = "Unique identifier is required.")
@Getter
@Setter
@Id
@Column(name = "id")
private UUID id;
// Refers to the container ProductEntity
// Using OneToOne with MapsId, so: ProductProfitabilityEntity.id = ProductEntity.id
@Valid
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "id")
@MapsId
private ProductEntity product;
}
The Issue
When I try to save ProductEntity, I get the following error:
.springframework.orm.ObjectOptimisticLockingFailureException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [br.triersistemas.cloud.platform.desktop.entity.productprofitabilityentity.ProductProfitabilityEntity#fb01b3e0-f12e-4380-b82a-2f2882fadaf1]
My Understanding of the Problem:
Hibernate sees that ProductProfitabilityEntity already has an ID and tries to fetch it from the database to determine whether it should perform an update or an insert. However, since the entity does not exist yet, it likely throws this exception.
I didn't expect that, because there is no @GeneratedValue and the entity does not exist, Hibernate would insert it with the provided ID instead of failing.
If I manually set the id of ProductProfitabilityEntity to null before saving, everything works fine—Hibernate properly inserts it and maps the relationship. However, since my API receives fully populated replicated data (which used to work before), setting the ID to null is not an ideal solution.
What Changed in Hibernate 6.6?
Before the update, this issue didn’t occur. I am trying to understand
- What has changed in Hibernate 6.6 that is now causing this behavior?
- Is there a better solution than manually setting ProductProfitabilityEntity.id = null before saving ProductEntity?
I recently updated my project from Hibernate 5.4 to Hibernate 6.6, and now I’m encountering an error that wasn’t happening before.
I have two entities: ProductEntity
and ProductProfitabilityEntity
, which are part of the same model and share the same ID. These entities are replicated from another microservice, meaning they arrive fully populated, including their IDs. Because of this, there is no @GeneratedValue annotation on their ID fields, as the IDs are assigned externally and must remain unchanged.
ProductEntity has a one-to-one relationship with ProductProfitabilityEntity. ProductProfitabilityEntity uses @MapsId, ensuring its ID is always the same as the ProductEntity ID. Both entities reference each other:
- ProductEntity has a profitability field referencing ProductProfitabilityEntity.
- ProductProfitabilityEntity has a product field referencing ProductEntity.
ProductEntity:
package br.triersistemas.cloud.platform.desktop.entity.product;
import br.triersistemas.cloud.database.entity.AuditingExternalEntity;
import br.triersistemas.cloud.platform.desktop.entity.productprofitability.ProductProfitabilityEntity;
import jakarta.persistence.*;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import java.util.UUID;
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@Entity
@Table(name = "product")
public class ProductEntity extends AuditingExternalEntity {
@Getter
@Setter
@Id
@Column(name = "id")
private UUID id;
@Getter
@Setter
@Column(name = "product_code")
private Long productCode;
// Contains one ProductProfitabilityEntity
@Valid
@OneToOne(mappedBy = "product", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private ProductProfitabilityEntity profitability;
}
ProductProfitabilityEntity:
package br.triersistemas.cloud.platform.desktop.entity.productprofitability;
import br.triersistemas.cloud.database.entity.AuditingEntity;
import br.triersistemas.cloud.platform.desktop.entity.product.ProductEntity;
import jakarta.persistence.*;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import java.util.UUID;
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@Entity
@Table(name = "product_profitability")
public class ProductProfitabilityEntity extends AuditingEntity {
@NotNull(message = "Unique identifier is required.")
@Getter
@Setter
@Id
@Column(name = "id")
private UUID id;
// Refers to the container ProductEntity
// Using OneToOne with MapsId, so: ProductProfitabilityEntity.id = ProductEntity.id
@Valid
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "id")
@MapsId
private ProductEntity product;
}
The Issue
When I try to save ProductEntity, I get the following error:
.springframework.orm.ObjectOptimisticLockingFailureException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [br.triersistemas.cloud.platform.desktop.entity.productprofitabilityentity.ProductProfitabilityEntity#fb01b3e0-f12e-4380-b82a-2f2882fadaf1]
My Understanding of the Problem:
Hibernate sees that ProductProfitabilityEntity already has an ID and tries to fetch it from the database to determine whether it should perform an update or an insert. However, since the entity does not exist yet, it likely throws this exception.
I didn't expect that, because there is no @GeneratedValue and the entity does not exist, Hibernate would insert it with the provided ID instead of failing.
If I manually set the id of ProductProfitabilityEntity to null before saving, everything works fine—Hibernate properly inserts it and maps the relationship. However, since my API receives fully populated replicated data (which used to work before), setting the ID to null is not an ideal solution.
What Changed in Hibernate 6.6?
Before the update, this issue didn’t occur. I am trying to understand
- What has changed in Hibernate 6.6 that is now causing this behavior?
- Is there a better solution than manually setting ProductProfitabilityEntity.id = null before saving ProductEntity?
- Fot to mention that, if i persist the ProductProfitabilityEntity before saving the Product, everything works fine too. – Nikolas Trapp Commented Mar 11 at 14:10
1 Answer
Reset to default 0Solved by removing @MapsId from ProductProfitabilityEntity.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744789562a4593831.html
评论列表(0条)