本人初学hibernate,希望大家多多指教!
我假设person和card的多对一的关系(实际这两者的关系不是多对一)
他们对应的映射文件是:
person.hbm.xml
<!----><hibernate-mapping schema="hibernatequickuse">
<class name="mypack.person" table="person">
<id name="id" column="id" type="java.lang.Integer">
<generator class="identity">
</id>
<property name="name" column="name" type="java.lang.String" not-null="true"></property>
<many-to-one name="mycard" column="card_id" class="mypack.Card" cascade="all"></many-to-one>
</class>
</hibernate-mapping>
Card.hbm.xml
<!----><hibernate-mapping>
<class name="mypack.Card" table="card">
<id name="id" column="ID" type="java.lang.Integer">
<generator class="identity">
</id>
<property name="name" column="NAME" type="java.lang.String" not-null="true"></property>
</class>
</hibernate-mapping>
假设当我们先把many-to-one中的cascade属性值去掉,改为:
<many-to-one name="mycard" column="card_id" class="mypack.Card"></many-to-one>
然后执行如下代码:
person p=new person();
p.setName("jack01");
Card c=new Card();
c.setName("card0031");
p.setMycard(c);
Session session=null;
Transaction tran=null;
try{
session=factory.openSession();
tran=session.beginTransaction();
session.save(p);//为什么是update,而不是Insert
tran.commit();
。。。。。。。
执行结果本来应该会报一个异常,因为只持久化了person对象。而card是临时对象,所以当hibernate自动清理缓存中的持久化对象时会发现p引用了c临时对象,而在person表中对应的card_id字段值为0,这说明person持久化对象的状态和数据库的记录不一致,所以应该会抛出异常!但是它却并没有抛出异常,
而是插入了一条person记录,其card_id=0这是为什么???
Hibernate: insert into hibernatequickuse.person (name, card_id) values (?, ?)
当我把cascade="all"加上去之后,本来这时应该是先插入card记录,然后插入Person记录。但结果却是:
Hibernate: insert into hibernatequickuse.person (name, card_id) values (?, ?)
Hibernate: update card set NAME=? where ID=?
而且抛出异常,表示无法更新!这又是为什么????????
Exception executing batch:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
表结构如下:
--
-- 表的结构 card
CREATE TABLE card
(
id
int(11) NOT NULL auto_increment,
name
varchar(20) collate latin1_general_ci NOT NULL,
PRIMARY KEY (id
)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=7 ;
CREATE TABLE person
(
id
int(11) NOT NULL auto_increment,
name
varchar(32) collate latin1_general_ci NOT NULL,
card_id
int(11) unsigned NOT NULL,
PRIMARY KEY (id
),
KEY card_id
(card_id
)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=4 ;
POJO如下:
person
package mypack;
public class person implements java.io.Serializable{
private int id;
private String name;
private Card mycard;
public person(){
}
private void setId(int id){
this.id=id;
}
public void setName(String name){
this.name=name;
}
public void setMycard(Card mycard){
this.mycard=mycard;
}
public int getId(){
return this.id;
}
public String getName(){
return this.name;
}
public Card getMycard(){
return this.mycard;
}
}
Card
package mypack;public class Card {
private int id;
private String name;public Card(){
}
public void setId(int id){
this.id=id;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return this.name;
}
public int getId(){
return this.id;
}
}
问题补充
补充下:我是参照网友的教程来做的,地址是:http://ryanpoy.iteye.com/blog/189783
奇怪的是他的结果是正确的!程序里面唯一不同的是我主键的设置上,我用的是auto_increment,映射xml中用的是identity!
问题补充:
谢谢kulinglei的回答,问题是我将cascade="save-update"; 它也没报任何异常啊,正常的情况应该是会报你所说的异常啊 !我把源码上传下,能帮我看看吗?
问题补充:
这是源码,希望大家帮帮忙!
问题补充:
谢谢etank帮忙,但我也用的是hibernate3的包,并且把identity改为了native。把cascade设为none,结果还是没报任何异常啊?我用的是mysql的数据库