【问题标题】:Soft delete cascade with Eclipselink DescriptorCustomizer使用 Eclipselink DescriptorCustomizer 软删除级联
【发布时间】:2012-10-22 20:54:20
【问题描述】:

亲爱的程序员朋友们,我来寻求帮助:

我正在使用 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 发布

谢谢!

【问题讨论】:

  • 嗨,Bart,错误消息可能具有误导性(未知列 ACTIVE),但以防万一,您能否验证 ARTICLE 表有一个名为 ACTIVE 的列?
  • 另外,命名您正在使用的 EclipseLink 版本也是值得的。
  • 您还可以显示两个实体和异常堆栈。它发生在任何类别上,还是只能在特定情况下重现?
  • @RobKielty 我可以确认 ACTIVE 列存在,但不像我第一次说的那样完全在 ARTICLE 表中。它实际上是 ITEM 表中的一列。这可能是原因吗?

标签: java jpa eclipselink


【解决方案1】:

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

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

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

第二个问题是:

#id instead of #ID

区分大小写。

谢谢你帮助我!

【讨论】:

  • 支持回归并解开谜团!没有什么比有人进来,问一个问题,解决它然后什么也没说更糟糕的了。尊重。
【解决方案2】:

每当一个类实现 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

【讨论】:

    猜你喜欢
    • 2010-10-05
    • 2016-05-13
    • 1970-01-01
    • 2015-07-10
    • 2013-06-19
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多