JPA entity relation in table which sharing same key as foreign and primary?

Viewed 266

Now, I have two tables.

1st Table (Object Table):

RefNo (PK) --> auto ascending
Type
Status
...

2nd Table (Object Detail Table):

RefNo (PK) --> FK reference from 1st Table
PolicyNo
DepNo
...

Entity for Object.

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long refnno;

  @OneToOne(mappedBy = "obejctTwo")
  private ObjectDetail objectDetail;

  private String type;

  private String status;

Entity for ObjectDetail

  @Id
  private long refnno;

  @OneToOne
  @JoinColumn(name = "refnno")
  @MapsId
  private Object object;

  private String policyNo;

  private String depNo;

How can I save the Object using jpaRepository for Object which include ObjectDetail inside Object JSON but without knowing the reffno(PK) which is auto generated by db.

{
    "objectDetail": {
        "policyNo": "12345678",
        "depNo": "ABC"
    },
    "type": "new",
    "status": "pending"
}
1 Answers

Would it not be possible to cascade the saving with the annotation @OneToOne(cascade = CascadeType.PERSIST) in the class Object?

I would then create the two objects with the available details, set the relationship and save the class Object.

object.setObjectDetail(objectDetail);
objectdetail.setObject(object);
repository.save(object);

The key of object would be set automatically and objectDetail would get the key from object.

Edit: Entity Example

I was slightly surprised that the code did not work. Therefore, I implemented this for myself. It works perfectly with Spring Boot version 2.3.2.RELEASE and spring-boot-starter-data-jpa.

Your issue might be @OneToOne(mappedBy = "obejctTwo") because this mapping does not exist.

Object

@Entity
public class Object {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long refnno;

    @OneToOne(mappedBy = "object",
            cascade = CascadeType.ALL,
            orphanRemoval = true)
    private ObjectDetail objectDetail;

    private String type;

    private String status;

    public setObjectDetail(ObjectDetail objectDetail) {
        this.objectDetail = objectDetail;
        objectDetail.setObject = this;
    }

    // Getters and remaining setters...
}

I added a slightly modified setter for objectDetail which helps to keep the bidirectional OneToOne mapping synchronised.

BTW: I changed the datatype of refnno to the object Long. Classes are considered to be better for database entities because than you can test them properly for null. Furthermore, this id can then be used for a JpaRepository<Object, Long>.

ObjectDetail

@Entity
public class ObjectDetail {

    @Id
    private Long refnno;

    @OneToOne
    @JoinColumn(name = "refnno")
    @MapsId
    private Object object;

    private String policyNo;

    private String depNo;

    // Getters and setters...
}

Repository and Execution

I created a simple repository.

public interface ObjectRepository extends JpaRepository<Object, Long> {
}

I then used the save(Object entity) method to persist a new Object with a new ObjectDetail.

Object object = new Object();
object.setType("new");
ObjectDetail objectDetail = new ObjectDetail();
objectDetail.setPolicyNo = "999";

object.setObjectDetail(objectDetail);

objectRepository.save(object);
Related