如何在 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_CONTENT
table。
现在从您的代码中,您可以从任何一侧访问这两个实体,例如 - file.getFileContent()
或 fileContent.getFile()
我有 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;
}
我也按照
我做错了什么?
============================================= ======================
编辑于 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_CONTENT
table。现在从您的代码中,您可以从任何一侧访问这两个实体,例如 -
file.getFileContent()
或fileContent.getFile()