Альтернативный способ принудительного ограничения внешнего ключа с использованием весенней загрузки и спящего режима - PullRequest
0 голосов
/ 13 июня 2019

Существуют ли альтернативные способы применения ограничений внешнего ключа с помощью JPA, Hibernate и т. Д., Чтобы свести к минимуму данные, хранящиеся в POJO?

У меня есть проект начальной загрузки с классами User и Form Model, Dao и Controller, который подключен к базе данных MySQL. Пользователь может иметь много форм, но форма может иметь только одного пользователя. Так что отношения один ко многим. Чтобы применить ограничение внешнего ключа, я использую аннотацию @OneToMany со списком. При таком дизайне, когда я использую метод HTTP GET в почтальоне, один пользователь возвращает пользователю И все его / ее связанные формы, что мне не нравится. Есть ли другой способ применить ограничение внешнего ключа, чтобы мне не нужно было хранить всю информацию в классе User, но при этом обеспечивалась ссылочная целостность в базе данных?

Ниже мой класс пользователя. Внизу я создаю Список типа Form и аннотирую его аннотацией @OneToMany, а затем сообщаю ему, с каким атрибутом в классе формы присоединиться к нему, используя @ JoinColumn

package org.hoa.HOA_Website.WebsiteDatabaseAPI.Entities;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.List;


@Entity
@Table
public class User {

    @Id
    @GeneratedValue
    @Column(name = "user_id", insertable = false, updatable = false)
    private Long userID;

    @NotBlank
    @Column(length = 30, nullable = false)
    private String firstName;

    @NotBlank
    @Column(length = 30, nullable = false)
    private String lastName;

    @NotBlank
    @Column(length = 30)
    private String middleName;

    @NotBlank
    @Column(length = 14)
    private String phoneNumber;

    @NotBlank
    @Column(length = 50, unique = true, nullable = false)
    private String email;

    @Column(nullable = false)
    private Boolean admin;

    private int age;

    @NotBlank
    @Column(length = 100, nullable = false)
    private String passwordHash;

    @OneToMany(targetEntity = Form.class, cascade = CascadeType.ALL)
    @JoinColumn(name = "submitter_id")
    private List<Form> formsMade;
/*
Getters and Setters Below
*/

Теперь под классом формы. Над отправителем у меня есть столбец, названный так, что он будет соответствовать аннотации @JoinColumn. Это гарантирует, что все идентификаторы отправителя, отправленные методом POST, имеют совпадающий идентификатор пользователя.

package org.hoa.HOA_Website.WebsiteDatabaseAPI.Entities;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table
public class Form {

    @Id
    @GeneratedValue
    private Long formID;

    @Column(nullable = false)
    private Date dateSubmitted;

    @Column(name = "submitter_id", nullable = false)
    private Long submitter;

    @Column(nullable = false)
    private Boolean approvalStatus;

    @Column(length = 30, nullable = false)
    private String formType;
/*
Getters and Setters Below
*/

НО, когда я выполняю метод GET, чтобы найти всех пользователей. Я получаю всех пользователей и связанные с ними формы.

[
    {
        "userID": 1,
        "firstName": "Jane",
        "lastName": "Doe",
        "middleName": "Halyard",
        "phoneNumber": "1234567890",
        "email": "janedoe@gmail.com",
        "admin": false,
        "age": 20,
        "passwordHash": "klsjfougalsdg2e98y54e982ajsdng924uierg",
        "formsMade": [
            {
                "formID": 5,
                "dateSubmitted": "2019-06-11T12:25:43.000+0000",
                "submitter": 1,
                "approvalStatus": false,
                "formType": "ConstructionForm"
            },
            {
                "formID": 6,
                "dateSubmitted": "2019-06-11T12:25:43.000+0000",
                "submitter": 1,
                "approvalStatus": false,
                "formType": "HardshipForm"
            }
        ]
    },
    {
        "userID": 2,
        "firstName": "John",
        "lastName": "Doe",
        "middleName": "Michael",
        "phoneNumber": "0987654321",
        "email": "johndoe@gmail.com",
        "admin": true,
        "age": 32,
        "passwordHash": "klsjfougalsdg2e98y5423bt49sdgajsdng924uierg",
        "formsMade": [
            {
                "formID": 3,
                "dateSubmitted": "2019-06-11T12:25:43.000+0000",
                "submitter": 2,
                "approvalStatus": false,
                "formType": "HardshipForm"
            }
        ]
    }
]

Итак, наконец, есть ли способ обеспечить ссылочную целостность, но при этом не хранить так много на Пользователе? Надеюсь, больше похоже на реляционные структуры данных и просто сохранить внешний ключ в форме?

1 Ответ

0 голосов
/ 13 июня 2019

Я думаю, что вы ищете это DTO .

Существуют ли альтернативные способы применения ограничений внешнего ключа с помощью JPA, Hibernate и т. Д.... чтобы минимизировать данные, хранящиеся в POJO?

Обсуждение порядка POJO немного неточно.Ваши сущности определяют ORM , и они должны быть определены как есть.Вы должны подумать о том, какие данные вы возвращаете.Ваш entiteis на самом деле не хранит данные , но вы заполняете их всеми данными и возвращаете все эти данные, если вы запрашиваете и возвращаете их такими, какие они есть, поэтому их также используют в качестве DTO.

Кажется, что вы возвращаете Collection<User> (таким образом, сущности) в качестве ответа.

Вместо этого вы должны вернуть коллекцию DTO - скажем - Collection<SimpleUserDTO>, где DTO может быть как:

public class SimpleUserDTO {
    public Long userID;
    public String firstName;
    public String lastName;
    public String middleName;
    public String phoneNumber;
    public String email;
    public Boolean admin;
    public int age;
    public String passwordHash;
    // NOTE: no formsMade here!
}

Таким образом, ваш Controller метод должен вызывать Service метод, который возвращает эту коллекцию DTO, которые он получает от некоторого Repository метода, либо уже сопоставленного как DTO, либо как сущностиэтот метод Service затем отображает один за другим DTO.

В вашем методе Service вы можете отображать значения сущностей в DTO - поле за полем или, возможно, с помощью библиотеки, такой как ModelMapper - но лучше всегоПо моему мнению, вы реализовали бы метод Repository Projection или Tuple запрос), который заполняет этот DTO прямо из запроса и позволяетметод Service вызывает это.

И после всего этого очень уродливого, но простого способа добиться того же самого, просто зациклите пользователей в вашем контроллере и установите formsMade в null, но это, наконец, очень неэффективнорешений и не будет гибким способом передать все эти материалы для конвертации позже с другими результатами и т. д. *

Есть много вещей, которые можно объяснить более подробно, но я надеюсь, что с этой информацией вы сможетечтобы найти больше информации от SO или где-либо еще в соответствующей документации.

И: конечно же, вам необходимо отобразить обратно из DTO в сущность, а затем при передаче данных в Controller.

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