Spring @OneToMany проблемы - PullRequest
       17

Spring @OneToMany проблемы

0 голосов
/ 13 апреля 2020

Выполнение проекта с посылочным сервисом. Я создал OrderItem API и Dispatcher API. Теперь я хочу связать потом отношениями. Идея такова: диспетчер может иметь много элементов. У OrderItem может быть только один диспетчер. Если вы удалите диспетчера, его пункты заказа также должны go. Я уже создал немного, но я так запутался здесь и не могу закончить sh эту вещь логически. Кто-нибудь подскажет мне, как мне решить эту проблему?

Нужно ли ставить отношения с обеих сторон или только с одной из них?

Когда мне нужно создавать конструкторы с аргументами? Потому что в классе сущностей у вас не должно быть конструкторов arg ...?

Класс OrderItem:

@Entity
public class OrderItem {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @NotBlank(message = "Order weight is required")
    private String weight;
    @NotBlank(message = "Order dimensions are required")
    private String dimensions;
    @NotBlank(message = "Order origin is required")
    private String origin;
    @NotBlank(message = "Order destination is required")
    private String destination;
    @NotNull(message = "Order comment cannot be null")
    private String comment;

    @ManyToOne
    private Dispatcher dispatcher;

    public OrderItem() {

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getWeight() {
        return weight;
    }

    public void setWeight(String weight) {
        this.weight = weight;
    }

    public String getDimensions() {
        return dimensions;
    }

    public void setDimensions(String dimensions) {
        this.dimensions = dimensions;
    }

    public String getOrigin() {
        return origin;
    }

    public void setOrigin(String origin) {
        this.origin = origin;
    }

    public String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        this.destination = destination;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public Dispatcher getDispatcher() {
        return dispatcher;
    }

    public void setDispatcher(Dispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }
}

Класс OrderController:

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    OrderService service;

    @Autowired
    private MapValidationErrorService mapValidationErrorService;

    @GetMapping("/{dispatcherId}/orders")
    public List<OrderItem> getAllOrderItems(@PathVariable int dispatcherId) {
        return service.getAllOrderItems(dispatcherId);
    }

    @PostMapping("/{dispatcherId}/orders")
    public ResponseEntity<?> saveOrder(@Valid @RequestBody OrderItem orderItem, @PathVariable int dispatcherId, BindingResult result) {

        ResponseEntity<?> errorMap = mapValidationErrorService.MapValidationService(result);

        if (errorMap != null) {
            return errorMap;
        }

        orderItem.setDispatcher(new Dispatcher(dispatcherId, "", "", ""));
        service.insertOrUpdate(orderItem);
        return new ResponseEntity<String>("Order was created successfully", HttpStatus.CREATED);
    }

    @PutMapping("/update")
    public ResponseEntity<?> updateOrder(@Valid @RequestBody OrderItem orderItem, BindingResult result) {

        ResponseEntity<?> errorMap = mapValidationErrorService.MapValidationService(result);

        if (errorMap != null) {
            return errorMap;
        }

        service.insertOrUpdate(orderItem);
        return new ResponseEntity<String>("Order was updated successfully", HttpStatus.OK);
    }

    @GetMapping("/all")
    public Iterable<OrderItem> getAllOrders() {
        return service.findAllOrders();
    }

    @DeleteMapping("/{orderId}")
    public ResponseEntity<String> deleteOrder(@PathVariable int orderId) {

        if (service.findById(orderId) == null) {
            throw new CustomErrorException("Order doesn't exist, check order id");
        }

        service.deleteOrder(orderId);
        return new ResponseEntity<String>("Order with ID " + orderId + " was deleted", HttpStatus.OK);
    }

    @GetMapping("/{orderId}")
    public ResponseEntity<OrderItem> getOrderById(@PathVariable int orderId) {
        OrderItem item = service.findById(orderId);

        if (service.findById(orderId) == null) {
            throw new CustomErrorException("Order id not found - " + orderId);
        }

        return new ResponseEntity<OrderItem>(item, HttpStatus.OK);
    }
}

Класс диспетчера:

@Entity
public class Dispatcher {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @NotBlank(message = "Dispatcher first name is required")
    private String firstName;
    @NotBlank(message = "Dispatcher last name is required")
    private String lastName;
    @NotBlank(message = "Dispatcher email name is required")
    private String email;
    @NotBlank(message = "Dispatcher email is required")
    private String password;
    @NotBlank(message = "Dispatcher phone number is required")
    private String phoneNumber;

    public Dispatcher() {

    }

    public Dispatcher(int id, String firstName, String lastName, String email) {
        super();
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

Класс DispatcherController:

@RestController
@RequestMapping("/dispatcher")
public class DispatcherController {

    @Autowired
    DispatcherService service;

    @Autowired
    private MapValidationErrorService mapValidationErrorService;

    @PostMapping("/save")
    public ResponseEntity<?> saveDispatcher(@Valid @RequestBody Dispatcher dispatcher, BindingResult result) {

        ResponseEntity<?> errorMap = mapValidationErrorService.MapValidationService(result);

        if (errorMap != null) {
            return errorMap;
        }

        service.insertOrUpdate(dispatcher);
        return new ResponseEntity<String>("Dispatcher was created successfully", HttpStatus.CREATED);
    }

    @GetMapping("/all")
    public Iterable<Dispatcher> getAllDispatchers() {
        return service.findAllDispatchers();
    }

    @GetMapping("/{dispatcherId}")
    public ResponseEntity<?> getDispatcherById(@PathVariable int dispatcherId) {

        Dispatcher dispatcher = service.findById(dispatcherId);

        if (service.findById(dispatcherId) == null) {
            throw new CustomErrorException("Dispatcher id not found - " + dispatcherId);
        }

        return new ResponseEntity<Dispatcher>(dispatcher, HttpStatus.OK);
    }

    @DeleteMapping("/{dispatcherId}")
    public ResponseEntity<?> deleteDispatcher(@PathVariable int dispatcherId) {

        if (service.findById(dispatcherId) == null) {
            throw new CustomErrorException("Dispatcher doesn't exist, check dispatcher id");
        }

        service.deleteDispatcher(dispatcherId);
        return new ResponseEntity<String>("Order with ID " + dispatcherId + " was deleted", HttpStatus.OK);
    }

    @PutMapping("/update")
    public ResponseEntity<?> updateDispatcher(@Valid @RequestBody Dispatcher dispatcher, BindingResult result) {

        ResponseEntity<?> errorMap = mapValidationErrorService.MapValidationService(result);

        if (errorMap != null) {
            return errorMap;
        }

        service.insertOrUpdate(dispatcher);
        return new ResponseEntity<String>("Dispatcher was updated successfully", HttpStatus.OK);
    }
}

Ответы [ 2 ]

0 голосов
/ 13 апреля 2020

Основное отличие состоит в том, что двунаправленные отношения дают вам доступ в обоих направлениях. так что вы можете получить доступ к другой стороне без каких-либо запросов. Это работает и для каскадных действий.

Двунаправленный @OneToMany генерирует лучший DML, потому что @ManyToOne владеет отношением.

Однонаправленный @ManyToOne или двунаправленный @OneToMany более эффективны, чем однонаправленный @OneToMany.

До JPA 2.0 это однонаправленное направление @OneToMany использовало таблицу соединений для управления связью между родительскими и дочерними строками. Таким образом, более высокая стоимость чтения (объединение 3 таблиц) и записи (вставка 3 таблиц).

Начиная с JPA 2.0 для однонаправленного @OneToMany, вы должны использовать его в соотношении с @JoinColumn

С @JoinColumn ассоциация @OneToMany контролирует дочернюю таблицу FK .. и поэтому нет необходимости в дополнительной соединительной таблице.

Но с точки зрения производительности нет ничего лучше, чем двунаправленные ассоциации.

Плюсы однонаправленной @OneToMany -> simplicity.

По второму вопросу: NoArg требуется только для персистентной среды (например, Hibernate). Но вы можете (и должны) использовать свои собственные конструкторы для создания consistent объектов.

0 голосов
/ 13 апреля 2020

Я думаю, вы неправильно определили отношения. И да, вам нужен конструктор без аргументов. Это помогает Hibernate отображать значения из базы данных в java объекты при извлечении данных из базы данных

При условии, что вы собираетесь использовать однонаправленное отображение,

@Entity
public class OrderItem {

    @ManyToOne( cascade = CascadeType.ALL )
    @JoinColumn(name = <foriegn_key_column in orderItem table i.e. id>)
    private Dispatcher dispatcher;
}

@Entity
public class Dispatcher {

    private List<OrderItem > orders;
}
...