双向一对一映射@OneToOne
双向一对一的实例我已经上传到GitHub,entrance项目上了,感兴趣的可以下载下来跑跑,这里讲两个在运行过程中遇到的问题。
问题一:上一篇博客的最后我留下了问题。一对一关联查询注解@OneToOne的实例详解
问题点:文章的最后,单向一对一程序在执行save语句的时候,分别执行了下面的语句:
Hibernate: select person0_.id as id1_2_1_, person0_.name as name2_2_1_, person0_.pet_id as pet_id3_2_1_, pet1_.id as id1_3_0_, pet1_.pet_class as pet_clas2_3_0_, pet1_.pet_name as pet_name3_3_0_ from person person0_ inner join pet pet1_ on person0_.pet_id=pet1_.id where person0_.id=?
Hibernate: insert into pet (pet_class, pet_name) values (?, ?)
Hibernate: insert into person (name, pet_id) values (?, ?)
Hibernate: insert into pet (pet_class, pet_name) values (?, ?)
Hibernate: update person set name=?, pet_id=? where id=?
这里我感觉很奇怪的地方就是执行了内连接,所以导致都没有查到。
再看看双向一对一执行的语句:
Hibernate: select husband0_.hid as hid1_1_1_, husband0_.hid_card as hid_card2_1_1_, husband0_.hname as hname3_1_1_, husband0_.w_id as w_id4_1_1_, wife1_.wid as wid1_6_0_, wife1_.wid_card as wid_card2_6_0_, wife1_.wname as wname3_6_0_ from husband husband0_ left outer join wife wife1_ on husband0_.w_id=wife1_.wid where husband0_.hid=?
Hibernate: insert into wife (wid_card, wname) values (?, ?)
Hibernate: insert into wife (wid_card, wname) values (?, ?)
Hibernate: update husband set hid_card=?, hname=?, w_id=? where hid=?
Hibernate: update husband set hid_card=?, hname=?, w_id=? where hid=?
双向一对一连接的话第一句执行的是左连接,所以能查到数据,这样就能直接更新了。
问题二:异常:在使用fastJson作为工具,将数据库查到的数据转换成fastJson输出,抛出了:java.lang.StackOverflowError: null
这个异常就是堆栈溢出,可以很明显的看出来,是因为husband对象与wife之前嵌套,在序列化的时候出现了这个异常。网上搜了一些,大多是List集合的嵌套,从中找到些蛛丝马迹。解决的方法:
方法一:把wife中husband的属性不序列化,加上属性transient,加上序列属性serialVersionUID
private static final long serialVersionUID = 8091602122698339709L; @Id // id自动生成 @GeneratedValue @Column(name = "wid") private Long wid; @Column(name = "wname") private String wname; @Column(name = "wid_card") private String widCard; @OneToOne(mappedBy = "wife",cascade=CascadeType.ALL) @JsonBackReference private transient Husband husband;
方法二:重新字节写toString方法,不要使用系统自己生成的(这里也有技巧)。
husband.toString()
@Override public String toString() { return "{\"hid\":\"" + hid + "\",\"hname\":\"" + hname + "\",\"hidCard\":\"" + hidCard + "\",\"wife\":" + wife + "} "; }
wife.toString()
@Override public String toString() { return "{\"wid\":\"" + wid + "\",\"wname\":\"" + wname + "\",\"widCard\":\"" + widCard + "\"} "; }
我的代码中采用了第二种方法。