mysqlspringspring-bootjpadbase

How to save entity with a composite primary key using IdClass


I have one to many relation between table signees & orders.

Signee Entity :

@Entity(name = "signees")
@IdClass(SigneePK.class)
public class SigneesEntity implements Serializable {

    private static final long serialVersionUID = 589098617333093930L;
    
    @Id
    @Column(length = 25, nullable = false)
    private String receiverType;
    
    @Id
    @Column(nullable = false, length = 150)
    private String emailSignee;

    @Id
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "files_id")
    private NuFileEntity nuFileDetails;

    @OneToMany(mappedBy="signee", cascade = CascadeType.ALL)
    private List<OrderEntity> orders;

    ....
}

SigneePk class:

public class SigneePK implements Serializable {
    
    private static final long serialVersionUID = -3098783129616840483L;
    private String receiverType;
    private String emailSignee;
    private NuFileEntity nuFileDetails;
    
    public String getReceiverType() {
        return receiverType;
    }
    public void setReceiverType(String receiverType) {
        this.receiverType = receiverType;
    }
    public String getEmailSignee() {
        return emailSignee;
    }
    public void setEmailSignee(String emailSignee) {
        this.emailSignee = emailSignee;
    }
    public NuFileEntity getNuFileDetails() {
        return nuFileDetails;
    }
    public void setNuFileDetails(NuFileEntity nuFileDetails) {
        this.nuFileDetails = nuFileDetails;
    }

}

and Order Entity:

@Entity(name = "orders")
public class OrderEntity implements Serializable {

    private static final long serialVersionUID = 4981007112274762119L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    
    @ManyToOne
    @JoinColumn(name="account_id", nullable=true)
    private AccountEntity account;

    
    @ManyToOne
    @MapsId("SigneePK")
    private SigneesEntity signee;

and what I called at Controller :

OrderDto orderResp = orderService.orderSignature(user, file);   

then on service implementation :

    @Override
    public OrderDto orderSignature(UserDto user, NuFileDTO nuFileDto) {

        OrderDto returnVal = new OrderDto();
        try {

            NuFileEntity file = new NuFileEntity();
            OrderEntity oe = new OrderEntity();
            SigneesEntity se = new SigneesEntity();
            //SigneePK se = new SigneePK();
            file.setFileId(nuFileDto.getFileId());
            file.setFileName(nuFileDto.getFileName());
            file.setFileType(nuFileDto.getFileType());
            file.setFileUploadTimestamp(nuFileDto.getFileUploadTimestamp());
            file.setFolder(nuFileDto.getFolder());
            file.setLastUpdatedTimestamp(nuFileDto.getLastUpdatedTimestamp());
            **se.setEmailSignee("me");**
            se.setReceiverType("signee");
            se.setNuFileDetails(file);
            oe.setSignee(se);
            oe.setPrice(1000);
            oe.setRequestTimestamp(Utils.getJakartaCurrentTimestamp());
            AccountEntity acc = new AccountEntity();
            acc.setId(1);
            oe.setAccount(acc);
        
            orderRepo.save(oe);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return returnVal;
    }

and finally error I got:

Caused by: java.sql.SQLException: Field 'signees_email_signee' doesn't have a default value

So my question how do I set that fields, because I thought I did that at my Implementation by this command: se.setEmailSignee("me");

please help me....Thank you in advance


Solution

  • This isn't a MapsID situation as you don't have a SigneePK mapping within your OrderEntity. The relationship is just an ID, so should be annotated as @Id. Since OrderEntity has a composite PK similar to SigneesEntity but with more columns (id+SigneePK), you need another composite pk class with those two attributes exactly:

    @Entity(name = "orders")
    @IdClass(OrderPK.class)
    public class OrderEntity implements Serializable {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
        
        @Id
        @ManyToOne
        @JoinColumns( {
          @JoinColumn(name="files_id", referencedColumnName="files_id"),
          @JoinColumn(name="email_signee", referencedColumnName="email_signee"),
          @JoinColumn(name="receiver_type", referencedColumnName="receiver_type")} )
        private SigneesEntity signee;
        ..
    }
    
    public class OrderPK {
        private long id;
        private SigneePK signee;
        
        public long getId() {
            return receiverType;
        }
        public void setId(long id) {
            this.id = id;
        }
        public SigneePK getSignee() {
            return signee;
        }
        public void setSignee(SigneePK signee) {
            this.signee = signee;
        }
    }