这篇文章是这个的延续职位我有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<MyFriends> Friends; public DlFaceBook(){} public void setFbId(String FbId) { this.FbId = FbId; } public void setFriends(Collection<MyFriends> friends) { this.Friends = friends; } public Collection<MyFriends> 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如下,它很简单:
<hibernate-mapping> <class name="DlUser" table="Users"> <id name="Id" column="id" > <generator class="sequence"> <param name="sequence">userseq</param> </generator> </id> <property name="firstName"> <column name="FirstName" /> </property> <property name="lastName"> <column name="LastName"/> </property> <many-to-one name="FaceBook" class="DlFaceBook" cascade="all" column="dlpId" unique="true" /> </class> </hibernate-mapping>
DlFacebook.hbm.xml看起来像这样:
<hibernate-mapping> <class name="DlFaceBook" table="dlfacebook"> <id name="dlpId" type="java.lang.Long" column="dlpId"> <generator class="increment" /> </id> <property name="fbId"> <column name="fbId" /> </property> <bag name="Friends"> <key column="me_Id" /> <one-to-many class="MyFriends"/> </bag> </class> </hibernate-mapping>
然后MyFriends.hbm.xml看起来像这样:
<hibernate-mapping> <class name="MyFriends"> <composite-id name="myFriendId" class="MyFriends$MyFriendsId"> <key-property name="meId"/> <key-property name="myFrId"/> </composite-id> <many-to-one name="me" class="DlFaceBook" insert="false" update="false"/> <many-to-one name="myFriend" class="DlFaceBook" insert="false" update="false"/> </class> </hibernate-mapping>
当我执行查询时,出现以下错误:
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> myFriends = new ArrayList<MyFriends>(); public Collection<MyFriends> getMyFriends() { return myFriends; } public void setMyFriends(Collection<MyFriends> myFriends) { this.myFriends = myFriends; } /** * add convenience method */ public void addFriend(Facebook myFriendFacebook) { myFriends.add(new MyFriends(this, myFriendFacebook)); } }
MyFriends
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(); } } }
映射
<hibernate-mapping package="br.com._3845772.model.domain"> <class name="User"> <id name="id"> <generator class="native"/> </id> <many-to-one cascade="all" class="Facebook" name="facebook"/> </class> <class name="Facebook"> <id name="id"> <generator class="native"/> </id> <bag cascade="all" name="myFriends"> <key column="ME_FACEBOOK_ID" update="false"/> <one-to-many class="MyFriends"/> </bag> </class> <class name="MyFriends"> <composite-id class="MyFriends$MyFriendsId" name="myFriendId"> <key-property column="ME_FACEBOOK_ID" name="meId"/> <key-property column="MY_FRIEND_FACEBOOK_ID" name="myFriendId"/> </composite-id> <many-to-one class="Facebook" column="ME_FACEBOOK_ID" insert="false" name="me" update="false"/> <many-to-one class="Facebook" column="MY_FRIEND_FACEBOOK_ID" insert="false" name="myFriend" update="false"/> </class> </hibernate-mapping>
还有这个样本
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 (?, ?)
几个注意事项
现在为什么用MutableLong(用Long属性 封装 )而不是Long呢?
Number及其子类(Long为Number)是不可变的。因此,如果要让Facebook.id(由数据库配置)与其对应的MyFriend $MyFriendId.meId共享相同的值,则必须使用MutableLong。当数据库设置Facebook.id时,MyFriend $MyFriendId.meId将自动获得其最新值。但是,如果您使用MutableLong,就会发生这种情况。