[英]JPA + Spring: Mapping a foreign key column to a ID based on the value received before persisting the entity
如果這是一個愚蠢的問題,請原諒我,但我對JPA和Spring非常新。 我想知道是否有人可以幫助解決以下問題,因為我在StackOverflow和谷歌上進行了大量搜索,但找不到我的用例的任何示例。 可能是我錯過了關鍵字,因為我不知道在JPA中調用這種映射是什么。
所以基本上,我正在嘗試開發一個REST API來從數據庫中檢索和插入記錄,並且我有兩個表,即CLIENT_MASTER
和TITLE
。
CLIENT_MASTER
的架構如下所示,
CREATE TABLE CLIENT_MASTER (
ID INT GENERATED BY DEFAULT AS IDENTITY(START WITH 1000),
TITLE_ID INT,
FIRST_NAME VARCHAR(255),
MIDDLE_NAME VARCHAR(255),
LAST_NAME VARCHAR(255),
PRIMARY KEY (ID)
);
同樣, TITLE
表的方案是,
CREATE TABLE TITLE (
ID INT GENERATED BY DEFAULT AS IDENTITY,
TITLE VARCHAR(10),
PRIMARY KEY (ID)
);
CLIENT_MASTER
表具有以下外鍵約束,
ALTER TABLE CLIENT_MASTER ADD CONSTRAINT TITLE_ID FOREIGN KEY (TITLE_ID) REFERENCES TITLE;
兩個表的實體定義如下,
import java.io.Serializable;
...
import lombok.Setter;
@Entity
@Table(name = "CLIENT_MASTER")
@Getter
@Setter
public class ClientMaster implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", updatable = false, nullable = false)
private Integer id;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "TITLE_ID")
private Title title;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "MIDDLE_NAME")
private String middleName;
@Column(name = "LAST_NAME")
private String lastName;
}
import java.io.Serializable;
....
import lombok.Setter;
@Entity
@Table(name = "TITLE")
@Getter
@Setter
public class Title implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", updatable = false, nullable = false)
private Integer id;
@Column(name = "TITLE")
private String title;
}
在我的休息控制器中,我在下面插入新客戶端
@RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<?> create(@RequestBody ClientMaster cm) {
cmrepository.create(cm);
HttpHeaders headers = new HttpHeaders();
ControllerLinkBuilder linkBuilder = linkTo(methodOn(CompanyController.class).get(cm.getId()));
headers.setLocation(linkBuilder.toUri());
return new ResponseEntity<>(headers, HttpStatus.CREATED);
}
其中cmrepository
是其實例,
@Repository
public class CMRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
public void create(ClientMaster cm) {
entityManager.persist(cm);
}
}
我在發布請求中發送以下json,我想要的是將標題值從TITLE
表映射到其各自的id,並插入具有正確標題ID的記錄。
{
"title": {
"title": "Mr"
},
"firstName": "XXX",
"middleName": "YYY",
"lastName": "ZZZ",
}
有了上面的說明,當前行為是對於CLIENT_TABLE
每個記錄插入,在TITLE
表中創建了一條新記錄,這不是我想要的。
有誰能指出我正確的方向,如何實現這一目標?
非常感謝。
持久性提供程序無法自動采用id by field值本身。
你必須:
title
獲取Title
條目。 ClientMaster
上設置title
..否則不執行任何操作並允許級聯持久保存該值。 在ClientMaster
對象上使用merge
而不是persist
:
cmrepository.merge(cm);
我不認為不插入它是一個好主意,因為你已經定義了一個forgien密鑰關系,它總是更好地為標題表存儲所有ID。
感謝大伙們
我遵循Maciej的建議,現在我的控制器如下所示
@RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<?> create(@RequestBody ClientMaster company) {
//fetch and set title.
company.setTitle(titleService.get(company.getTitle().getTitle()));
companyService.create(company);
HttpHeaders headers = new HttpHeaders();
ControllerLinkBuilder linkBuilder = linkTo(methodOn(CompanyController.class).get(company.getId()));
headers.setLocation(linkBuilder.toUri());
return new ResponseEntity<>(headers, HttpStatus.CREATED);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.