Размещение сущности с помощью manyToMany, ManyToOne - PullRequest
0 голосов
/ 08 февраля 2019

Я всегда избегал отношений @xToX в своих API, но, наконец, хотел попробовать, и я борюсь с этим.Мне удалось заставить методы get возвращать мне правильную информацию с любой рекурсивностью (по крайней мере, я сделал часть), и теперь я хочу опубликовать данные в моем API с этими взаимосвязями (и, кажется, работает до сих пор).

Итак, у меня есть несколько объектов: книга, стиль книги, категория книг и автор.У книги есть только один автор (даже если она иногда ложная, но, поскольку я читаю только Sci-Fi, она сделает свое дело), ​​и у автора есть много книг (то же самое для категории).И у стиля может быть много книг, также у книг может быть много стилей.

Итак, я выбрал @ManyToOne для свойства автора книги и @OneToMany для свойства книги автора (то же самое для категории).И между стилем и буквой @ManyToMany

Я хочу иметь возможность опубликовать книгу в своем API следующим образом, используя идентификаторы автора и стиля:

{
    "isbn": "15867jhg8",
    "title": "Le portrait de Dorian Gray",
    "author": 1,
    "category":1,
    "style": [1,2,3]
}

У меня естьмои свойства помечены @JsonBackReference, @JsonManagedReference, @JsonSerialize, @JsonIdentityInfo, но я действительно думаю, что мог бы сделать это слишком много ...

Я не уверен в том, как я использовал@JsonSerialize, ни @JsonIdentityInfo.Я опустил бесполезные свойства, чтобы сделать пример «простым».

Итак, давайте углубимся.

Сначала класс Book:

@Entity
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id"
)
public class Book implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false)
    private Integer id;

    private String isbn;

    private String title;

    @ManyToOne
    @JoinColumn(name="category_id", nullable = false)
    @JsonBackReference(value = "category")
    private BookCategory category;

    @ManyToOne
    @JoinColumn(name="author_id", nullable = false)
    @JsonBackReference(value = "author")
    private Author author;

    @ManyToMany
    @JsonManagedReference(value = "styles")
    @JsonSerialize(using = BookStyleListSerializer.class)
    private List <BookStyle> styles;
}

Затем класс автора:

@Entity
@JsonIdentityInfo (
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id"
)
public class Author implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false)
    private Integer id;

    @OneToMany(mappedBy = "author")
    @JsonManagedReference(value = "authorBooks")
    @JsonSerialize(using = BookListSerializer.class)
    private List <Book> books;
}

Поскольку категория совершенно одинакова, я только вставляю свойство books:

@OneToMany(mappedBy = "category")
@JsonManagedReference(value = "categoryBooks")
@JsonSerialize(using = BookListSerializer.class)
private List <Book> books;

И, наконец, мой класс bookStyle:

@Entity
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id"
)
public class BookStyle implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false)
    private Integer id;

    @ManyToMany
    @JsonManagedReference(value = "styleBooks")
    @JsonSerialize(using = BookListSerializer.class)
    private List <Book> books;
}

Сериализатор один и тот же, меняется только тип:

public class BookStyleListSerializer extends StdSerializer <List <BookStyle>> {

public BookStyleListSerializer() {
    this(null);
}

public BookStyleListSerializer(Class<List<BookStyle>> t) {
    super(t);
}

@Override
public void serialize(List <BookStyle> bookStyles, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

    List<Integer> ids = new ArrayList <> (  );
    for (BookStyle style: bookStyles){
        ids.add(style.getId ());
    }
    jsonGenerator.writeObject ( ids );
}
}

Из того, что я понял (и, поскольку английский не является моим родным языком, я мог бы неправильно понять кое-что здесь и там во время кодирования):

  • @JsonBackReference должен использоваться для свойства, которое мы не хотим сериализовать, в отличие от @JsonManagedReference
  • @JsonSerialize - это пользовательский сериализатор, так чтоэлементы будут сериализованы так, как мы хотим (в данном случае, только с использованием идентификаторов)

И, как это может быть очевидно для некоторых из вас: ничего из того, что я кодировал, не работает для публикации данных,вот исключение, как я получил, когда я публикую что-то через API (и это в два раза, неошибка вставки копии):

.c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.rz.librarian.domain.entity.Author]]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot handle managed/back reference 'categoryBooks': no back reference property found from type [collection type; class java.util.List, contains [simple type, class com.rz.librarian.domain.entity.Book]] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.rz.librarian.domain.entity.Author]]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot handle managed/back reference 'categoryBooks': no back reference property found from type [collection type; class java.util.List, contains [simple type, class com.rz.librarian.domain.entity.Book]]

Я много чего перепробовал, но после трех дней по этому вопросу я хотел попросить (плакать?) помощи.

Спасибо, ребята, и извините за длинный пост!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...