Отношение JPA ManyToOne - Невозможно вставить строку с внешним ключом - PullRequest
0 голосов
/ 19 декабря 2018

В моем проекте Spring Boot у меня есть две модели, Building и Location.Я пытаюсь создать новое местоположение, которое принадлежит зданию.

Это мои модели:

Модель местоположения

public class Location implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Getter
    private Integer id;

    @NonNull
    @Getter
    @Setter
    private String name;

    @NonNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "building_id")
    @JsonBackReference("building-location")
    @ToString.Exclude
    @Getter
    @Setter
    private Building building;

    @Getter
    @Setter
    @Version
    @Column(name = "lock_version")
    private Integer lockVersion;
}

Модель здания

public class Building implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Getter
    private Integer id;

    @NonNull
    @Size(max = 10)
    @Getter
    @Setter
    private String name;

    @OneToMany(mappedBy = "building")
    @JsonManagedReference("building-location")
    @ToString.Exclude
    @Getter
    private List<Location> locations = new ArrayList<>();

    @Getter
    @Setter
    @Version
    @Column(name = "lock_version")
    private Integer lockVersion;

}

Это мой контроллер

@PostMapping(value = "/")
@ResponseBody
public ResponseEntity<Response> createLocation(@Valid @RequestBody Location location) {
    Location createdLocation = locationRepository.save(location);
    return ResponseEntity.ok(
            new Response(ResponseTypeEnum.Success, createdLocation)
    );
}

Это тело запроса:

{
    "name": "Kitchen",
    "building": {
        "id": 9
    }
}

У меня проблемав том, что JPA не распознает объект building , поэтому при попытке сохранить Location я получаю следующее исключение:

SQLException Column 'building_id' cannot be null. Query is: insert into location (building_id, lock_version, name) values (?, ?, ?), parameters [<null>,0,'Yoga Room'].

Если я получу здание из БД, используя findById, а затем установлю свойство здания в объекте Location, оно будет работать, но я не хочу получать объект для сохранения экземпляра Location.Я просто хочу передать внешний ключ и сохранить новый экземпляр.

Могу ли я сделать это с JPA?

Ответы [ 4 ]

0 голосов
/ 04 сентября 2019

Решение, которое сработало для меня, следующее:

package com.deportes.deportes_api.tablas;

import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Version;
import javax.validation.constraints.Pattern;
import com.fasterxml.jackson.annotation.JsonProperty;

@Entity
@Table(name="disciplina")
public class Disciplina {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Version
    private Integer version;
    @Pattern(regexp = ".*([a-zA-Z0-9]{2}$)",message="El nombre debe contener letras y     numeros con una longitud mínima de 2 caracteres")
    private String nombre;

    @Pattern(regexp = "([a-zA-Z0-9]{10})",message="El código debe tener 10 caracteres")
    @Column(name="codigo", unique=true)
    private String codigo;

    private Date createdAt;
    private Date updatedAt;

    @ManyToOne
    @JoinColumn(name="deporte_id", insertable=false, updatable=false)
    private Deporte deporte; 

    @Column(name = "deporte_id")
    @JsonProperty("deporte_id")
    private Integer deporte_id;

    public String getNombre() {
        return nombre;
    }
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
    public String getCodigo() {
        return codigo;
    }
    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }
    public Integer getVersion() {
        return version;
    }
    public void setVersion(Integer version) {
        this.version = version;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Date getCreatedAt() {
        return createdAt;
    }
    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }
    public Date getUpdatedAt() {
        return updatedAt;
    }
    public void setUpdatedAt(Date date) {
        this.updatedAt = date;
    }
}
0 голосов
/ 19 декабря 2018

Исключение заявляет о нулевом 'building_id', что означает, что id переданного building объекта null или не был правильно установлен.

И это потому, что при попыткедля save экземпляра Location JPA попытается установить свойство building из вашего запроса, поэтому ему нужно установить id, но он не смог сделать это , поскольку вы не определилиsetter метод для id в вашей Building сущности.

Вам необходимо изменить код, чтобы добавить метод установки с аннотацией lombok:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Getter
@Setter
private Integer id; 
0 голосов
/ 20 декабря 2018

Попробуйте добавить поле buildingId в классе Location

public class Location implements Serializable {

    ... 

    @Getter
    @Setter
    @Column(name = "building_id")
    @JsonProperty("building_id")
    private Integer buildingId;

    ...
}

Затем вы можете отправить запрос с телом

{
    "name": "Kitchen",
    "building_id": 9
}
0 голосов
/ 19 декабря 2018

Вы не можете сделать это в JPA, но одно из альтернативных решений, если вы не хотите использовать базу данных для объекта Building, - вместо этого загрузить ссылку:

Building b = buildingRepository.getOne(buildingId);
location.setBuilding(b);
Location createdLocation = locationRepository.save(location);

Помните, что вседолжен находиться в одной транзакции.

getOne javadoc:

Возвращает ссылку на объект с заданным идентификатором.

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