4

亲爱的程序员,我向您寻求以下帮助:

我正在使用 EclipseLink 作为我的应用程序的 ORM,并尝试在我的一个实体(文章)上实现软删除,并在删除具有 OneToMany 关系的类别时级联删除这些文章。

当我删除一篇文章时,一切都按预期工作,但是当我删除一个包含 n 篇文章的类别时,我得到一个例外。我正在使用 DescriptorCustomizer 来完成软删除。

具有以下实现的 DescriptorCustomizer(请参阅org.eclipse.persistence.config.DescriptorCustomizer ):

public class ArticleCustomizer implements DescriptorCustomizer {

    @Override
    public void customize(ClassDescriptor classDescriptor) throws Exception {
       classDescriptor.getQueryManager().setDeleteSQLString("UPDATE article SET ACTIVE = '0' WHERE id = #id");
    }
}

我要保存的实体:

抽象项目

@Entity
@Table(name = "item")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class AbstractItem extends BaseEntity {
    @ManyToOne
protected Category category;
}

文章

@Entity
@DiscriminatorValue("article")
@Customizer(value=ArticleCustomizer.class)
public class Article extends AbstractItem {

}

类别

@Entity
@Customizer(value=CategoryCustomizer.class)
public class Category extends BaseEntity {

    @OneToMany(cascade = CascadeType.REMOVE)
    @JoinTable(name = "category_items", joinColumns = @JoinColumn(name = "category_id"), inverseJoinColumns = @JoinColumn(name = "item_id"))
    protected List<AbstractItem> items = new ArrayList<AbstractItem>();

    @OneToMany(cascade = CascadeType.REMOVE)
    @JoinTable(name = "category_subcategories", joinColumns = @JoinColumn(name = "category_id"), inverseJoinColumns = @JoinColumn(name = "parent_category_id"))
    protected List<Category> categories = new ArrayList<Category>();
}

当我尝试级联删除具有 n 篇文章的类别时的错误:

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'ACTIVE' in 'field list'
Error Code: 1054
Call: UPDATE article SET ACTIVE = '0' WHERE id = ?
bind => [null]

我可以看到 id 被绑定为 null,但是我不明白为什么。有人可以指导我正确的方向吗?

  1. Eclipselink 版本:2.4.0
  2. 春天:3.1.2发布

谢谢!

4

2 回答 2

4

很抱歉耽误了你的时间。解决方案就在我面前:

classDescriptor.getQueryManager().setDeleteSQLString("UPDATE item SET ACTIVE = '0' WHERE id = #ID");

定制器的正确表应该是ITEM而不是ARTICLE。奇怪的是,它适用于单个文章的删除,但不适用于级联。

第二个问题是:

#id instead of #ID

它区分大小写。

谢谢你帮助我!

于 2012-10-23T19:34:59.037 回答
0

每当一个类实现时DescriptorCustomizer,我建议将其编码包装为:

public static class MyCustomizer implements DescriptorCustomizer {
    @Override
    public void customize(ClassDescriptor descriptor) throws Exception {
        try {
           ...
           ... your functionality 
           ...
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
}

原因是DescriptorCustomizer当日志记录设置低于FINER(这非常冗长)时,会产生静默失败。然后异常不会传播到“外部”,您不会收到它们的通知,也无法找出失败的原因。

或者,您可以将 EMF 属性PersistenceUnitProperties.LOGGING_LEVEL级别设置为SessionLog.FINER_LABEL.

于 2015-10-18T15:36:22.423 回答