Home > Net >  Hibernate - Persisting child entity containing parent entity
Hibernate - Persisting child entity containing parent entity

Time:01-27

Getting errors while trying to persist child entity (MsgRetry) when trying to get an entity of parent entity (Msg) where the parent PK (msg_id) is the FK in the child entity.

Errors like: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property

The parent entity, does not need to know about the child entity (at least i don't think it needs to, to work). Once the child entity is persisted I'm trying to also persist the parent entity. I can work around this by not having the parent entity in the child entity and the call the associated repositories. However, I don't think it's as clean as what I'm attempting but obviously more difficult/ complex.

Thanks for any advice on best practices or how to achieve this if this is a good solution.

tables:

msg
msg_id pk
msg_status msg_status
msg_retry
msg_id fk
count
timestamp

model:

@Entity
@Table(name="msg")
public class Msg {
    
    @Id
    @Column(name = "msg_id")
    @GeneratedValue(strategy = generationtype.sequence, generator = "msg_id_seq_gen")
    @SequenceGenerator(name = "msg_id_seq_gen", sequencename = "msg_id_seq", allocationsize = 1)
    private Long msgId;
    
    @Column(name = "msg_status", nullable = false)
    private String msgStatus;
    
    ...
    
    //getters setters
}
@Entity
@Table(name = "msg_retry")
public class MsgRetry {

    @Id
    @Column(name = "msg_id") //fk
    private Long msgId;
    
    @Column(name = "count")
    private Long count;
    
    @Generated(value = GenerationTime.ALWAYS)
    @Column(name = "timestamp")
    private Date timestamp;
    
    @JoinColumn(name = "msg_id")
    @ManyToOne(targetEntity = Msg.class, fetch = FetchType.LAZY)
    private Msg msg;
    
    public Msg getMsg() { return msg; }
         
    public void setMsg(Msg msg) { this.msg = msg; }
}
public class BizLogic {

    MsgRetryRepository retryRepo
    
    public MsgRetry retry(Long msgId, String msgStatus) {
    
        MsgRetry mr = retryRepo.findById(msgId)
        
        if (mr !=null) {
            mr.set....
            mr.setMsg(mr.getMsg().setMsgStatus("XX"));
            
            ...
            
            retryRepo.save(mr);
        }   
    }
}

CodePudding user response:

how about add one id fields to MsgRetry class

CodePudding user response:

First, straighten out your IDs for MsgRetry. The FK should be good enough.

@Entity
@Table(name = "msg_retry")
public class MsgRetry {
    @Id
    @ManyToOne(optional = false)
    @JoinColumn(name = "msg_id")
    private Msg msg;
    
    @Column(name = "count")
    private Long count;
    
    @Generated(value = GenerationTime.ALWAYS)
    @Column(name = "timestamp")
    private Date timestamp;
    
    public Msg getMsg() { return msg; }
         
    public void setMsg(Msg msg) { this.msg = msg; }
}

Next, be sure MsgRetryRepository is properly sub-classed:

public interface MsgRetryRepository extends CrudRepository<MsgRetry, Msg>
{
  // Empty for now
}

Lastly, query the MsgRetry in the right way:

public class BizLogic {

    MsgRetryRepository retryRepo
    
    public MsgRetry retry(Msg msg, String msgStatus) {
    
        MsgRetry mr = retryRepo.findById(msg);        
        if (mr !=null) {
            // XXX I cannot tell from your logic what you are doing here.
            retryRepo.save(mr);
        }   
    }
}

What is your persistence layer? Maybe you can turn on debugging and visit the logs to see what is happening under the hood.

  •  Tags:  
  • Related