Spring Data REST Вступил в наследование
У меня есть Spring Data Repository
над одним объектом JPA. Этот объект подклассифицирован через объединенное наследование.
Spring У данных REST есть проблема, интерпретирующая эту структуру, по крайней мере автоматически. Или, может быть, я не понимаю использование Inheritance.JOINED
Любой запрос для любого объекта с Event
возвращает следующее:
{
cause: null,
message: "Cannot create self link for class com.foo.event.SubEvent! No persistent entity found!"
}
Возможно, я слишком много прошу, чтобы этот проект знал, как с этим справиться, но есть ли способ обхода, который бы сгруппировал все мои Events
под тем же /events
? Может быть, даже разрешить мне фильтровать по типу?
Я оставил основы структуры приложения ниже.
Event.java
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
@Type(value = SubEvent.class),
...
})
...
public class Event {
@Id
private long id;
...
}
SubEvent.java
@Entity
public class SubEvent extends Event {
private String code;
...
}
EventRepository.java
@RepositoryRestResource(path = "events")
public interface EventRepository extends PagingAndSortingRepository<Event, Long> {
...
}
Ответы
Ответ 1
Я думаю, что вам не хватает Discriminator
, чтобы JPA понял, какой подкласс использовать для данного объекта (как он знает иначе?).
Я склонен использовать абстрактные классы для наемных работников на основе подкласса, поэтому здесь приведен пример, подходящий для вас:
Event.java
@Entity
@DiscriminatorColumn(name = "type")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Event {
@Id
@GeneratedValue
public Long id;
public String type;
}
SubEvent.java
@Entity
@DiscriminatorValue("subevent")
@PrimaryKeyJoinColumn(name = "event_id")
public class PeeringService extends Service {
private String code;
}
С приведенным выше кодом вы заметите что-то нечетное - при создании пути ресурса для одного из этих объектов предполагается, что у вас есть Repository
для каждого подкласса и генерирует что-то вроде этого:
{
"type" : "subevent",
"code" : "bacon",
"_links" : {
"self" : {
"href" : "http://localhost:8081/subEvents/1"
},
"peeringService" : {
"href" : "http://localhost:8081/subEvents/1"
}
}
}
Это довольно легко исправить, но вам просто нужно добавить следующую аннотацию в базовый класс:
@RestResource(path = "events")
И он будет генерировать пути ресурсов, которые вы ожидаете!
Надеюсь, что это поможет:)
Ответ 2
Я попробовал вас в классе в простом проекте загрузки spring, и они не дали мне никаких проблем, и я не мог воспроизвести проблему, с которой вы сталкиваетесь. Однако поиск в приведенном вами сообщении об ошибке дает пару сообщений, которые предполагают, что вам нужно создать репозиторий SubEvent
, даже если вы его не используете, и что проблема возникает в более сложных проектах, например, с использованием REST.
Ссылка: Невозможно создать самостоятельную ссылку для класса X. Не найден постоянный объект.
Как выбрать MappingContext в spring -data-jpa (2x) + spring -rest-webmvc?
Итак, попробуйте добавить репозиторий SubEvent:
interface SubEventRepository extends CrudRepository<SubEvent, Long> {
}
Ответ 3
Я думаю, что проблема не имеет ничего общего с JPA, но это скорее круговая проблема сериализации. Поскольку вы не показали свою сущность, я могу только предположить, что сущность Subevent имеет отношение к другому (Sub) событию и что один Subevent ссылается на себя, что приводит к этой проблеме. Конечно, также возможно, что отношения не являются прямыми, а скорее некоторыми другими классами сущностей, такими как SubEvent → EntityG → Event.
Чтобы решить эту проблему, просто используйте DTO, в котором отображаются только все поля SubEvent, кроме тех, которые производят циклическую зависимость.
Ответ 4
Я опробовал немало вариантов, и никто не работал, как ожидалось, и всегда имел проблемы в одной точке (создание ссылок, сопоставление репозитория, сопоставление URL-адресов и т.д.).
Даже для разделенных репозиториев (по одному для каждого подтипа) я не имел успеха. Мое "грязное, а не рабочее" решение заключалось в том, чтобы постинвестировать ссылки для всех подтипов, используя реализацию ResourceProcessor
. Эта реализация в основном заменила имя подтипа именем типа на каждой ссылке, присутствующей на ресурсе.
Кроме того, был введен RelProvider
для обработки имен свойств разных типов.