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

Tony_Ynot :

I have 2 entities with the following mapping

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; 

}    

and 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;  

}   

So far this mapping is working fine as I can get File using fileContent.getDocFile().

So is it possible that I can map the FileContent within the File also? I tried to add the mapping in this way but it's not working, I always getting null when I access using file.getFileContent();

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

}  

I also tried with @MapsId and @PrimaryKeyJoinColumn as suggested in here but still not able to get it to work.

What am I doing wrong?

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

Edited on 8/8/2019

Thanks for Razib for the answer, and it's working perfectly. However I found that it's working when I select the FILE record form the DB, but not from a freshly saved FILE object.

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;

I'm not using the Cascade to save these entities. When I access the return file using file.getFileContent(); and it's null.

Razib :

What you are looking for is bidirectional one to one mapping. Now the mapping is done only one way. In bidirectional mapping, you need to put File reference in FileContent and vice versa. Check the following code snippet -

File:

@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

    } 

FileContent:

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

Notes:

  • The above code snippet will create the table named FILE_CONTENT with a column named FILE_ID.
  • FILE_ID is the foreign key referencing the primary key of FILE.ID.

  • Here in the association, the File entity is the parent, while the FileContent is the child. Because the foreign key is located in the FILE_CONTENT table.

  • Now from your code, you can access both entities from any side like - file.getFileContent() or fileContent.getFile()

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=132694&siteId=1