如何在 JPA 中映射没有外键的一对一关系?

How to map one to one relation with no foreign key in JPA?

我有 2 个具有以下映射的实体

FileContent.java

@Entity
@Table(name="FILE_CONTENT", schema="COMMON")
public class FileContent implements Serializable{

  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  @Column(name="ID")
  private Long id;

  @OneToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "FILE_ID")
  private File docFile; 

}    

File.java

@Entity
@Table(name="FILE", schema="COMMON")
public class File implements Serializable{

  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  @Column(name="ID")
  private Long id;

  @Column(name = "FILE_NAME")
  private String fileName;  

}   

到目前为止,这个映射工作正常,因为我可以使用 fileContent.getDocFile().

获得 File

那么我是否也可以将 FileContent 映射到 File 中? 我尝试以这种方式添加映射,但它不起作用,当我使用 file.getFileContent();

访问时,我总是得到 null
@Entity
@Table(name="FILE", schema="COMMON")
public class File implements Serializable{

  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  @Column(name="ID")
  private Long id;

  @Column(name = "FILE_NAME")
  private String fileName;  

  @OneToOne(mappedBy = "docFile", cascade = CascadeType.ALL)
  private FileContent fileContent;

}  

我也按照 中的建议尝试使用 @MapsId 和 @PrimaryKeyJoinColumn,但仍然无法正常工作。

我做错了什么?

============================================= ======================

编辑于 2019 年 8 月 8 日

感谢 Razib 的回答,它工作得很好。 但是我发现当我 select FILE 记录形成数据库时,它正在工作,但不是来自新保存的 FILE 对象。

File file = new File();
file.setFileName("sample.txt")
fileRepo.saveAndFlush(file);

File fileContent = new FileContent();
fileContent.set....;
fileContent.setFile(file);
fileContentRepo.saveAndFlush(fileContent);

return file;

我没有使用 Cascade 来保存这些实体。当我使用 file.getFileContent(); 访问 return file 并且它是 null.

您要查找的是双向一对一映射。现在映射仅以一种方式完成。在双向映射中,需要将 File 引用放在 FileContent 中,反之亦然。检查以下代码片段 -

文件:

@Entity
@Table(name="FILE", schema="COMMON")
public class File {

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="ID")
        private Long id;

        @Column(name = "FILE_NAME")
        private String fileName;

        @OneToOne(mappedBy = "file", cascade = CascadeType.ALL,
           fetch = FetchType.LAZY, optional = false)
        private FileContent details;  

        //constructors getters and setters

    } 

文件内容:

@Entity
@Table(name="FILE_CONTENT", schema="COMMON")
public class FileContent{

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="ID")
    private Long id;

    @Column(name = "FILE_NAME")
    private String fileName;  

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FILE_ID")
    private File file;   

    //constructors getters and setters
}

备注:

  • 上面的代码片段将创建名为 FILE_CONTENT 的 table 和一个名为 FILE_ID 的列。
  • FILE_ID是外键引用FILE.ID的主键。

  • 此处在关联中,File 实体是父实体,而 FileContent 是子实体。因为外键位于FILE_CONTENTtable。

  • 现在从您的代码中,您可以从任何一侧访问这两个实体,例如 - file.getFileContent()fileContent.getFile()