【问题标题】:How to map one to one relation with no foreign key in JPA?如何在 JPA 中映射没有外键的一对一关系?
【发布时间】:2019-12-14 20:58:20
【问题描述】:

我有 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;

}  

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

我做错了什么?

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

于 2019 年 8 月 8 日编辑

感谢 Razib 的回答,它运行良好。 但是,当我从数据库中选择 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(); 访问返回file 时,它是null

【问题讨论】:

    标签: java jpa jpa-2.0 hibernate-mapping one-to-one


    【解决方案1】:

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

    文件:

    @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
    }
    

    注意事项:

    • 上面的代码 sn -p 将创建一个名为FILE_CONTENT 的表,其中有一列名为FILE_ID
    • FILE_ID 是引用FILE.ID 主键的外键。

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

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

    【讨论】:

    • 感谢 Razib,您的回答完美无缺,但除此之外我还发现了另一个问题,并在该问题上进行了更新。感谢您是否可以查看它。谢谢。
    猜你喜欢
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 2015-07-18
    相关资源
    最近更新 更多