hibernate更新为null,然后尝试通过更新列删除

时间:2014-06-03 15:44:24

标签: java hibernate jpa

我只想要那些未使用的属性将从DB中删除(orphanRemoval = true)。 我得到的是它首先尝试更新refrence PRODUCT_ID,然后删除它。但由于参考是关键的一部分,所以不能。

父:

    @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;
    ...

它的孩子

    @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;
        ...

在我获取属性列表然后清除之后,我尝试提交

    ...
    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
    ...

有没有人知道为什么Hibernate会先尝试更新引用,然后删除它。我可以以某种方式阻止它。我想要的是那些未使用的子(属性)必须被删除而不仅仅是剪切引用。 ...

4 个答案:

答案 0 :(得分:1)

我认为关系存在问题。您必须映射实体,而不是它们的特定列。

我建议使用以下结构:

@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;
...

属性:

@Entity
@Table(name="ATTRIBUTE")
public class Attribute{

    ...

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PRODUCT_ID", nullable = false)
    protected Style style;
    ...

引用的父实体Style没有明确的ID。 Hibernate将其解析为实体。

为什么在属性类中使用如此复杂的ID?

B.T.W。:默认情况下,子实体没有确定性顺序,所以最好使用Set代替List

答案 1 :(得分:1)

似乎我的问题与此类似:

How can I map "insert='false' update='false'" on a composite-id key-property which is also used in a one-to-many FK?

@JoinColumn(name =&#34; PRODUCT_ID&#34;,referencedColumnName =&#34; PRODUCT_ID&#34;, insertable = false,updatable = false

答案 2 :(得分:1)

我在google上搜索此问题,但没有得到答案。 Hibernate在删除之前发出更新SQL,更新SQL尝试将非可空列设置为null,然后发生异常。我不知道为什么在删除之前Hibernate会更新更新。

最后我使用自定义删除JPQL而不是Spring Data JPA标准删除方法。

&#13;
&#13;
@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);
}
&#13;
&#13;
&#13;

答案 3 :(得分:0)

我有类似的问题。使用“ 可更新=假”对我有用。

您可以尝试以下代码:

@OneToMany(fetch = FetchType.LAZY,  cascade=CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "PRODUCT_ID", referencedColumnName = "PRODUCT_ID", updatable = false)
private Set<Attribute> attributes