问题描述
我想在我的数据库中存储房间详细信息和房间类型。我为 Room 创建了一个实体,如下所示。
@Data
@Entity
public class Room {
@Id
private String room_id;
private Boolean status;
private Double price;
private Long type;
private Long occupancy;
@OnetoOne(fetch = FetchType.LAZY,optional = true)
@JoinColumn(name = "type_id",nullable = false)
private RoomType roomType;
}
我创建了一个 RoomType 实体,如下所示:
@Data
@Entity
public class RoomType {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String type;
}
要在我的数据库中保存一个房间实体,以下是需要给出的请求正文格式
{
"room_id": "string","status": true,"price": 0,"roomType": {
"id": 1,"type": "string"
}
}
我希望请求正文如下
{
"room_id": "string","roomType": 1 # This the roomType foreign key
}
我想建立一对一的关系,因此在检索房间详细信息时,我将获得同样采用以下格式的roomType值。
{
"room_id": "string","roomType": {
"id": 0,"type": "string"
}
}
或者有没有更好的方法来处理spring boot中的这类问题??
解决方法
我认为这里有两个不同的概念:
- 服务中
Room
的内部表示(您使用的类及其关系) - 外部表示(由您的 API 公开的表示)
如果您希望这两种表示相同,您可以直接使用 Room
类序列化/反序列化数据(我认为这是您目前正在做的)。例如:
@Controller
class MyController {
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public Room createRoom(@RequestBody Room room) {
// Here room will be automatically deserialized from the request body
// Do stuff with the received room in here
// ...
// Here the returned room will be automatically serialized to
// the response body
return createdRoom;
}
}
但是,如果您不希望内部和外部表示相同,则可以使用 DTO 模式(数据传输对象)。 Spring here 中的示例。
现在,您将拥有三个不同的类,Room
和 DTO:
public class RoomRequestDTO {
private String room_id;
private Boolean status;
private Double price;
private Long type;
private Long occupancy;
private Integer roomType; // This is now an Integer
// Setters and Getters ...
}
public class RoomResponseDTO {
private String room_id;
private Boolean status;
private Double price;
private Long type;
private Long occupancy;
private RoomType roomType; // This is a RoomType instance
// Setters and Getters ...
}
现在,您的控制器将接收 RoomRequestDTO
并发送 RoomResponseDTO
:
@Controller
class MyController {
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public RoomResponseDTO createRoom(@RequestBody RoomRequestDTO roomReqDTO) {
Room room = ... // Convert from DTO to Room
// Do stuff with the received room in here
RoomResponseDTO roomRespDTO = ... // Convert to the DTO
return roomRespDTO;
}
}
这种方法还有一个优点,您现在可以在不影响 API 的情况下更改 Room
的内部表示。也就是说,您可以决定将 Room
和 RoomType
类合并为一个,而不影响外部表示。
注意:在我链接的示例中,它们使用 ModelMapper
库。如果你不想引入这种依赖,你可以简单地向 DTO 添加一个构造函数和一个方法
public RoomResponseDTO(Room room) {
// Manually asign the desired fields in here
this.id = room.getId();
// ...
}
public Room toRoom() {
Room room = new Room();
// Manually asing the desired field in here
room.setId(this.id);
// ...
return room;
}
然而,这种方法会使您在想要更改 Room
的表示时必须更改这些方法。 ModeMapper
库为您执行此操作。