双向OneToOne映射下toBuilder与Setter持久化效果差异问题
双向OneToOne映射下Setter与toBuilder设置关联的持久化差异原因
做数据库双向OneToOne映射的数据存储操作时,分别使用toBuilder和Setter两种方式设置实体关联关系,最终得到的数据库存储结果存在明显差异。
Setter方式实现代码
Question question = Question.builder().quest("What is Pythonn ?").answer(null).build(); Answer answer = Answer.builder().answer("Python is language").que(question).build(); answer.setQue(question); question.setAnswer(answer); Question question2 = Question.builder().quest("How are you ?").answer(null).build(); Answer answer2 = Answer.builder().answer("I am fine").build(); answer2.setQue(question2); question2.setAnswer(answer2); session.save(question); session.save(question2);
该方式执行后,question表和answer表的外键关联、数据内容均符合预期,双向关联持久化正常。
toBuilder方式实现代码
answer.toBuilder().que(question).build(); question = question.toBuilder().answer(answer).build(); answer2.toBuilder().que(question2).build(); question2 = question.toBuilder().answer(answer2).build();
该方式执行后,两张表的数据内容、外键关联均不符合预期,没有得到正确的存储结果。
差异核心原因
- toBuilder不会修改原实体,只会生成新实体
Lombok提供的toBuilder()方法的逻辑是:基于当前实体的属性拷贝生成一个新的Builder构造器,后续调用build()方法会返回一个全新的实体实例,全程不会修改原有实体的任何属性。你写的answer.toBuilder().que(question).build();、answer2.toBuilder().que(question2).build();两行,生成的新Answer对象没有赋值给任何变量,直接被丢弃,原answer、answer2对象里的关联属性始终是初始的null值,根本没有完成关联设置。 - toBuilder代码存在引用错误
给question2赋值的代码question2 = question.toBuilder().answer(answer2).build();,错误调用了第一个question实例的toBuilder方法,生成的新实体的问题内容是第一条数据的"What is Pythonn ?",而非预期的"How are you?",直接导致存储的数据内容错乱。 - Setter方式直接修改待持久化的原实体
Setter方法是直接修改后续要传入session.save()的原实体的属性值,双向OneToOne要求的两端实体互相持有对方引用的逻辑完全成立,JPA/Hibernate在持久化时能正确识别关联关系,因此可以正常写入外键、完成双向关联持久化。
内容的提问来源于stack exchange,提问作者Sumit Kumar
相关产品推荐
相关产品推荐

