Reputation: 1101
I want just that those attributes which are not used will get removed from DB (orphanRemoval=true). What I got is that it first tries to update the refrence PRODUCT_ID and then delete its. but as the refrence is part of the key it cannot.
Parent:
@Entity
@Table(name = "STYLE")
public class Style implements IterableById, Serializable {
...
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="PRODUCT_ID", referencedColumnName = "PRODUCT_ID")
private List<Attribute> attributes;
...
Its Child
@Entity
@Table(name="ATTRIBUTE")
public class Attribute{
@EmbeddedId
private Id id;
...
@Embeddable
public static class Id implements Serializable{
private static final long serialVersionUID = -8631874888098769584L;
@Column(name="PRODUCT_ID")
protected Long productId;
@Column(name="NAME")
protected String name;
@Column(name="COUNTRY_CODE")
protected String countryCode;
...
After i take a list of attributes and clear then, and thtne try to commit i get
...
Hibernate: update ATTRIBUTE set PRODUCT_ID=null where PRODUCT_ID=?
Hibernate: delete from ATTRIBUTE where COUNTRY_CODE=? and NAME=? and PRODUCT_ID=?
javax.persistence.RollbackException: Error while committing the transaction
Caused by: javax.persistence.OptimisticLockException: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
...
Does anyone know why Hibernate tries to update the reference first, and then deletes it. Can I somehow prevent it from. All I want is that those childs(attributes) which are not used have to get deleted and not just cut the reference. ...
Upvotes: 5
Views: 6735
Reputation: 131
I had similar issues. Using "updatable = false" has worked for me.
You can try out below code :
@OneToMany(fetch = FetchType.LAZY, cascade=CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "PRODUCT_ID", referencedColumnName = "PRODUCT_ID", updatable = false)
private Set<Attribute> attributes
Upvotes: 13
Reputation: 925
I search on google for this issue but did not get a answer. Hibernate issue a update SQL before delete, the update SQL try set a non-nullable column to null, then exception happen. I do not know why Hibernate issue update before delete.
At last I use custom delete JPQL instead of Spring Data JPA standard delete method.
@Repository
public interface ProductRepository extends PagingAndSortingRepository<Product, Long> {
Product findByName(String name);
String jpql_deleteById = "delete from Product p where p.id = :id";
@Modifying
@Query(jpql_deleteById)
void deleteById(@Param("id") Long id);
}
Upvotes: 3
Reputation: 1101
Seems like my issue is similar to this one:
@JoinColumn(name="PRODUCT_ID", referencedColumnName = "PRODUCT_ID", insertable = false, updatable = false)
Upvotes: 3
Reputation: 71
I think there is a problem about the relationship. You have to map entities, not specific columns of them.
I suggest the following construct:
@Entity
@Table(name = "STYLE")
public class Style implements IterableById, Serializable {
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "style", cascade=CascadeType.ALL, orphanRemoval = true)
private Set<Attribute> attributes;
...
And the attribute:
@Entity
@Table(name="ATTRIBUTE")
public class Attribute{
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PRODUCT_ID", nullable = false)
protected Style style;
...
There is no explicit ID for the referenced parent entity Style
. Hibernate resolve it to its entity.
Why do you use such a complicated ID in your attribute class?
B.T.W.: By default there is no deterministic order for child entities, so you should better use a Set
instead of List
Upvotes: 2