2010-10-02 75 views
1

這篇文章是本post映射相同的類關係 - 延續

一個延續我有DlUser類本類的每個對象可以具有DLFaceBook類和DlFaceBook的每個對象可以具有被映射爲myFriends好友。

我想映射的關係使用包映射,複合主鍵和靜態內部類的許多關係相同的類。我的代碼如下:

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

Facebook的用戶類看起來是這樣的,你可以看到我有objectes與類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 

我看到th當我們嘗試更新不存在的行時會發生錯誤,但是如何讓此代碼可以工作?

+0

你正在使用什麼數據庫? – Bozho 2010-10-02 12:54:20

+0

如果您試圖更新不存在的行,那該如何工作? – 2010-10-02 14:07:10

回答

3

只是Facebook和MyFriends

Facebook的注意添加方便的方法和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(由龍物業封裝),而不是龍?

編號及其小類(長是數字)是不可變的。所以,如果你想要Facebook.id(由數據庫配置)及其對應的MyFriend $ MyFriendId.meId 共享相同的值,則必須使用MutableLong。當數據庫設置Facebook.id時,MyFriend $ MyFriendId.meId將自動獲得其最新值。但是,如果您使用MutableLong,就會發生這種情況。

+0

It works :)非常感謝。我從你的例子中學到了很多東西。這對我來說非常高興。 – 2010-10-03 00:21:34

+0

1)這對我不起作用(改變'MyFriends'表中的一個組合鍵的值導致在該表中創建新記錄,刪除根本不起作用)。 2)這個解決方案可能工作,但僅用於將新記錄保存到「MyFriends」表中。當從數據庫加載Facebook實體時,Hibernate調用'MyFriendsId'上的默認構造函數,因此'MyFriendsId.meId'和'MyFriendsId.myFriendId'爲空,並且在某些時候拋出空例外。在默認的構造函數中創建新的實例會造成使用Mutable的目的?對象作爲ID(值仍然不共享)。 – mnn 2013-04-27 01:33:42