映射相同的类关系 – 延续

这篇文章是这篇文章的延续

我有DlUser类这个类的每个对象都可能有DLFaceBook类,而DlFaceBook的每个对象都可以拥有映射为myFriends的Friends。

我正在尝试使用包映射,复合主键和静态内部类来映射同一类的关系。 我的代码如下:

public class DlUser{ public DlUser(){} Long Id; String FirstName; String LastName; .... DlFaceBook fbuser; //// all requred getters and setters... } 

Facebook用户类看起来像这样,你可以看到我拥有MyFriends类的对象集合:

 public class DlFaceBook { private long dlpId; private String FbId; private Collection Friends; public DlFaceBook(){} public void setFbId(String FbId) { this.FbId = FbId; } public void setFriends(Collection friends) { this.Friends = friends; } public Collection getFriends() { return this.Friends; } public void setdlpId(long id) { this.dlpId = id; } public long getdlpId() { return this.dlpId; } public String getFbId() { return this.FbId; } } 

MyFriends类看起来像这样:

 public class MyFriends { private MyFriendsId myFriendId; private DlFaceBook me; private DlFaceBook myFriend; public MyFriendsId getmyFriendId(){ return this.myFriendId; } public void setmyFriendId(MyFriendsId fid){ this.myFriendId = fid; } public void setme(DlFaceBook me){ this.me = me; } public void setmyFriend(DlFaceBook friend){ this.myFriend = friend; } public DlFaceBook getme(){ return this.me ; } public DlFaceBook getmyFriend(){ return this.myFriend ; } public MyFriends(DlFaceBook me, DlFaceBook user){ this.me = me ; this.myFriend = user; this.myFriendId = new MyFriendsId(me.getdlpId(),user.getdlpId()); } public static class MyFriendsId implements Serializable { private long meId; private long myFrId; // getter's and setter's public MyFriendsId() {} public MyFriendsId(long meId, long myFriendId) { this.meId = meId; this.myFrId = myFriendId; } // getter's and setter's public long getmeId(){ return this.meId; } public void setmeId(Integer id){ this.meId = id; } public long getmyFrId(){ return this.myFrId; } public void setmyFrId(long id){ this.myFrId = id; } } } 

现在映射:

DlUser.hbm.xml如下所示,很简单:

     userseq            

DlFacebook.hbm.xml看起来像这样:

               

然后MyFriends.hbm.xml看起来像这样:

           

当我执行我的查询时,我收到以下错误:

 Hibernate: insert into dlfacebook (fbId, dlpId) values (?, ?) Hibernate: insert into Users (FirstName, LastName, email, twitter, birthday, dlpId, id) values (?, ?, ?, ?, ?, ?, ?) Hibernate: update MyFriends set me_Id=? where meId=? and myFrId=? Hibernate: update MyFriends set me_Id=? where meId=? and myFrId=? Oct 2, 2010 1:21:18 PM org.hibernate.jdbc.BatchingBatcher doExecuteBatch SEVERE: Exception executing batch: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85) at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70) at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:183) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206) at Test.main(Test.java:54) Oct 2, 2010 1:21:18 PM org.hibernate.event.def.AbstractFlushingEventListener performExecutions SEVERE: Could not synchronize database state with session org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85) at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70) at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:183) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206) at Test.main(Test.java:54) Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 

我看到当我们尝试更新不存在的行时会发生此错误,但是如何使此代码生效?

只是Facebook和MyFriends

Facebook Notice添加便利方法和MutableLong(后来我告诉你为什么要使用MutableLong)

 public class Facebook { private MutableLong id = new MutableLong(); public Long getId() { return id.longValue(); } public void setId(Long id) { this.id.setValue(id); } public MutableLong getIdAsMutableLong() { return id; } private Collection myFriends = new ArrayList(); public Collection getMyFriends() { return myFriends; } public void setMyFriends(Collection myFriends) { this.myFriends = myFriends; } /** * add convenience method */ public void addFriend(Facebook myFriendFacebook) { myFriends.add(new MyFriends(this, myFriendFacebook)); } } 

我的朋友

 public class MyFriends { private MyFriendsId myFriendId; public MyFriendsId getmyFriendId(){ return this.myFriendId; } public void setmyFriendId(MyFriendsId myFriendId){ this.myFriendId = myFriendId; } private Facebook me; public Facebook getme() { return this.me; } public void setme(Facebook me){ this.me = me; } private Facebook myFriend; public Facebook getmyFriend() { return this.myFriend; } public void setmyFriend(Facebook friend) { this.myFriend = friend; } public MyFriends() {} public MyFriends(Facebook meFacebook, Facebook myFriendFacebook){ this.me = meFacebook ; this.myFriend = myFriendFacebook; this.myFriendId = new MyFriendsId(meFacebook.getIdAsMutableLong(), myFriendFacebook.getIdAsMutableLong()); } public static class MyFriendsId implements Serializable { private MutableLong meId = new MutableLong(); public Long getMeId() { return this.meId.longValue(); } public void setMeId(Long id) { this.meId.setValue(id); } private MutableLong myFriendId = new MutableLong(); public Long getMyFriendId(){ return this.myFriendId.longValue(); } public void setMyFriendId(Long id) { this.myFriendId.setValue(id); } public MyFriendsId() {} public MyFriendsId(MutableLong meId, MutableLong myFriendId) { this.meId = meId; this.myFriendId = myFriendId; } @Override public boolean equals(Object o) { if (!(o instanceof MyFriendsId)) return false; MyFriendsId other = (MyFriendsId) o; return new EqualsBuilder() .append(getMeId(), other.getMeId()) .append(getMyFriendId(), getMyFriendId()) .isEquals(); } @Override public int hashCode() { return new HashCodeBuilder() .append(getMeId()) .append(getMyFriendId()) .hashCode(); } } } 

制图

                          

而这个样本

 Facebook meFacebook = new Facebook(); Facebook myFriendFacebook = new Facebook(); meFacebook.addFriend(myFriendFacebook); Session session = sessionFactory.openSession(); session.beginTransaction(); session.save(myFriendFacebook); session.save(meFacebook); session.getTransaction().commit(); session.close(); 

这给了我

 Hibernate: insert into Facebook values ( ) Hibernate: insert into Facebook values ( ) Hibernate: select myfriends_.ME_FACEBOOK_ID, myfriends_.MY_FRIEND_FACEBOOK_ID from MyFriends myfriends_ where myfriends_.ME_FACEBOOK_ID=? and myfriends_.MY_FRIEND_FACEBOOK_ID=? Hibernate: insert into MyFriends (ME_FACEBOOK_ID, MY_FRIEND_FACEBOOK_ID) values (?, ?) 

几个笔记

  • Hibernate 不支持自动生成复合主键。 您必须在保存之前设置其值
  • 您的数据库必须支持目标生成器策略 (如果您不知道数据库支持哪种生成器策略,则更喜欢使用本机策略)
  • 每个实体必须提供一个无参数构造函数

现在为什么MutableLong(由Long属性封装 )而不是Long?

Number及其子类(Long是一个Number) 是不可变的 。 因此,如果您希望Facebook.id(由数据库配置)和其对应的MyFriend $ MyFriendId.meId 共享相同的值,则必须使用MutableLong 。 当数据库设置Facebook.id时,MyFriend $ MyFriendId.meId自动获得其最新值。 但是如果你使用MutableLong就会发生这种情况。