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 implements Serializable{
private static final long serialVersionUID = -7637385223556379976L;
@Id
@Column(name = "msg_id")
private Long msgId;
@OneToOne
@JoinColumn(name="msg_id", referencedColumnName = "msg_id")
private Msg msg;
@Column(name = "count")
private Long count;
@Generated(value = GenerationTime.ALWAYS)
@Column(name = "timestamp")
private Date timestamp;
public MsgRetry() {
}
public MsgRetry(Msg msg, Long count) {
this.msg = msg;
this.count = count;
}
public MsgRetry(Long msgId, Long count) {
this.msgId = msgId;
this.count = count;
}
public Msg getMsg() {
return msg;
}
public void setMsg(Msg msg) {
this.msg = msg;
}
@Repository
public interface MsgRetryRepository extends JpaRepository<MsgRetry, Long>{
}
@Test
public void testSaveMsgByMsgIdRetry() {
msgRetryRepository.deleteAll();
List<Msg> msgs = msgRepository.findAll();
MsgRetry msgRetry = new MsgRetry(msgs.get(0).getMsgId(), 1L);
msgRetry = msgRetryRepository.save(msgRetry);
assertNotNull(msgRetry.getMsg()); // fails to load Msg entity
LOG.info("msgRetry: {}", msgRetry);
}
@Test
public void testSaveMsgRetryByMsg() {
msgRetryRepository.deleteAll();
List<Msg> msgs = msgRepository.findAll();
MsgRetry msgRetry = new MsgRetry(msgs.get(0), 1L);
msgRetry = msgRetryRepository.save(msgRetry);
assertNotNull(msgRetry.getMsg());
LOG.info("msgRetry: {}", msgRetry);
}
Errors out: org.springframework.orm.jpa.JpaSystemException: ids for this class must be manually assigned before calling save(): msgtest.MsgRetry;
how about add one id
fields to MsgRetry
class
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.