eclipselink запрашивает поле индикатора класса при использовании InheritanceType.TABLE_PER_CLASS

Я уже потратил несколько часов, пытаясь получить эту работу. Я использую политику истории, чтобы создать полную историзацию для некоторых из моих таблиц. Это определено в абстрактном классе. Тогда у меня есть нормальная сущность, реализующая этот класс и определяющая его поле. Затем я хотел использовать класс, который наследуется от высшего класса, но его таблица установлена ​​в таблицу истории. Это работало отлично, единственная проблема заключалась в том, что когда я выполнял запрос к историзированной таблице (lasso_warehandling_entry), он всегда возвращал мне результаты из исторического объекта (lasso_warehandling_entry_hist). Поэтому я добавил строку descriptor.getInheritancePolicy(). SetShouldReadSubclasses(false); что я где-то читал, что это должно решить мою проблему. К сожалению это не так. Теперь я всегда получаю следующее сообщение:

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
}

1 ответ

Это должно помочь:

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

От getInheritancePolicy()документация:

Следует соблюдать осторожность при использовании этого метода, поскольку он лениво инициализирует политику наследования.

Вызов этого дескриптора, который не использует наследование, вызовет проблемы, hasInheritance() всегда должен вызываться первым.

У меня такая же проблема, как и у вас.

В сообщении об ошибке говорится, что EclipseLink не может определить, запрашиваете ли вы LassoWarehandlingEntry или LassoWarehandlingEntryHist. (поле индикатора класса или метод извлечения класса должны быть установлены.) Следовательно, если вы запрашиваете LassoWarehandlingEntry, EclipseLink будет запрашивать как LassoWarehandlingEntry, так и LassoWarehandlingEntryHist. Итак, я думаю, что вы пытаетесь использовать

descriptor.getInheritancePolicy().setShouldReadSubclasses(false);

К сожалению, поскольку мы используем InheritanceType.TABLE_PER_CLASS, кажется, что мы не можем использовать аннотации дискриминатора (@DiscriminatorColumn и @DiscriminatorValue). Эти 2 аннотации предназначены только для 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 просто выполнит 1 запрос к таблице LassoWarehandlingEntry.

Надеюсь, что это поможет!

Другие вопросы по тегам