簡體   English   中英

JPA + Spring:根據持久化實體之前收到的值將外鍵列映射到ID

[英]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_MASTERTITLE

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值本身。

你必須:

  1. 首先按title獲取Title條目。
  2. 如果已獲取,則在ClientMaster上設置title ..否則不執行任何操作並允許級聯持久保存該值。
  3. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM