2010-10-02 73 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