eclipselink在使用InheritanceType.TABLE_PER_CLASS时要求类指示符字段

时间:2014-01-22 20:59:10

标签: java inheritance jpa eclipselink table-per-class

我已经花了几个小时试图完成这项工作。 我正在使用历史策略为我的一些表创建完整的历史记录。这是在抽象类中定义的。 然后我有一个正常的实体来实现这个类并定义它的字段。 然后我想使用一个从上层开始的类,但是它的表被设置为历史表。这是完美的,唯一的问题是,当我对历史表(lasso_warehandling_entry)进行查询时,它总是返回历史实体(lasso_warehandling_entry_hist)的结果。所以我添加了这条线     descriptor.getInheritancePolicy()setShouldReadSubclasses(假)。 我读到的地方,它应该解决我的问题。不幸的是它没有。 现在我总是得到以下信息:

Exception Description: The descriptor [RelationalDescriptor(dao.LassoWarehandlingEntry --> [DatabaseTable(lasso_warehandling_entry)])] has been set to use inheritance, but a class indicator field has not been defined. 
When using inheritance, a class indicator field or class extraction method must be set. 
Parent Descriptor: [RelationalDescriptor(org.rorotec.lasso.dao.LassoWarehandlingEntry --> [DatabaseTable(lasso_warehandling_entry)])]
Descriptor: RelationalDescriptor(dao.LassoWarehandlingEntry --> [DatabaseTable(lasso_warehandling_entry)])

由于我们为每个实体使用单独的表,因此使用指标字段没有多大意义。无论如何,我只是没有设法得到这个消息。 任何人都知道我应该如何解决这个问题? 代码看起来像这样:

@MappedSuperclass
@Customizer(abstractDao.HistoryCustomizer.class)
public abstract class AbstractAuditedOzlEntity {
// defined the columns all the autited classes have
...
}

public class HistoryCustomizer implements DescriptorCustomizer {

    public void customize(ClassDescriptor descriptor) {
        HistoryPolicy policy = new HistoryPolicy();
        policy.addHistoryTableName(descriptor.getTableName()  + "_hist");
        policy.addStartFieldName("start_date");
        policy.addEndFieldName("end_date");
        descriptor.setHistoryPolicy(policy);

        // This here I added afterwards, as described in the text, and is the reason for the error message i get
        descriptor.getInheritancePolicy().setShouldReadSubclasses(false);
     }
}

@Entity
// when i define the inhertiancetype already in the abstract class, it doesn't seem to have any influence, so I added it here.
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@Table(name = "lasso_warehandling_entry")
public class LassoWarehandlingEntry extends AbstractAuditedOzlEntity implements Serializable {
// define the specific stuff of this table
... 

}

@Entity
@Table(name = "lasso_warehandling_entry_hist")
@AttributeOverride(name="id", column=@Column(name="hist_id"))
public class LassoWarehandlingEntryHist extends LassoWarehandlingEntry {
...
// add the columns which only exist in the history tables like end_date
}

2 个答案:

答案 0 :(得分:0)

我面临与你相同的问题。

错误消息表明EclipseLink无法区分您是在查询LassoWarehandlingEntry还是LassoWarehandlingEntryHist。 (必须设置类指示符字段或类提取方法。)因此,如果查询LassoWarehandlingEntry,EclipseLink将同时查询LassoWarehandlingEntry和LassoWarehandlingEntryHist。所以我想你正在尝试使用

descriptor.getInheritancePolicy().setShouldReadSubclasses(false);

不幸的是,由于我们使用的是InheritanceType.TABLE_PER_CLASS,我们似乎无法使用鉴别器注释(@DiscriminatorColumn和@DiscriminatorValue)。这两个注释仅适用于InheritanceType.SINGLE_TABLE和InheritanceType.JOINED。 ClassExtractor也不起作用。有关详情,请访问https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Entities/Inheritance

无论如何,我通过创建一个抽象类来解决这个问题,该抽象类将由两个具体类继承。在你的情况下:


@MappedSuperclass
public abstract class AbstractLassoWarehandlingEntry extends AbstractAuditedOzlEntity implements Serializable {
// define the specific stuff of this table
... 

}


@Entity
@Table(name = "lasso_warehandling_entry")
public class LassoWarehandlingEntry extends AbstractLassoWarehandlingEntry implements Serializable {
// Empty class as the content is already defined in AbstractLassoWarehandlingEntry

}


@Entity
@Table(name = "lasso_warehandling_entry_hist")
@AttributeOverride(name="id", column=@Column(name="hist_id"))
public class LassoWarehandlingEntryHist extends AbstractLassoWarehandlingEntry {
...
// add the columns which only exist in the history tables like end_date
}

通过使用此方法,您可以从HistoryCustomizer类中删除以下行。


descriptor.getInheritancePolicy().setShouldReadSubclasses(false);

现在,如果您查询LassoWarehandlingEntry,EclipseLink将只对LassoWarehandlingEntry表执行1次查询。

希望这有帮助!

答案 1 :(得分:0)

这应该有帮助:

if (descriptor.hasInheritance()) {
    descriptor.getInheritancePolicy().setShouldReadSubclasses(false);
}

来自getInheritancePolicy() documentation

使用此方法时必须小心,因为它会延迟初始化继承策略。

在不使用继承的描述符上调用此方法会导致问题,必须始终首先调用hasInheritance()。