JPA ManyToOne关系-无法使用外键插入行

时间:2018-12-19 15:08:45

标签: hibernate spring-boot jpa

在我的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无法识别建筑对象,因此当我尝试保存位置时,出现以下异常:

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 :(得分:1)

尝试在Location类中添加buildingId字段

public class Location implements Serializable {

    ... 

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

    ...
}

然后您可以随身发送请求

{
    "name": "Kitchen",
    "building_id": 9
}

答案 1 :(得分:0)

您无法在JPA中执行此操作,但是,如果您不想访问Building实体的数据库,则可以选择一种替代解决方案,那就是加载引用:

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

请记住,所有内容都必须在同一笔交易中。

getOne javadoc:

  

返回对具有给定标识符的实体的引用。

答案 2 :(得分:0)

该异常声称存在一个空'building_id',这意味着传递的id对象的buildingnull或未正确设置。

那是因为当您尝试save实例时,JPA会尝试根据您的请求设置Location属性,因此它需要设置building但这不能做到这一点,因为您尚未在id实体中为setter 定义id方法。

您需要更改代码以添加带有lombok批注的setter方法:

Building

答案 3 :(得分:0)

对我有用的解决方案如下:

$result= $query->queryOne();
$this->setAttributes($result);