没有级联时,可以直接删除many方,但不能直接删除one方。。。
一对多,有级联关系时:
one-to-many的设置中:
one方的配置文件,set或list集合里配置cascade=“all”或者“all-delete-orphan”,相当于加了级联关系。
删除one方时,many方的相关数据也会被删掉。
但是要注意:
删除one方时,不能直接写“delete from One where id=?”
会报错误,类似于该记录还有关联的子记录,不能直接删除,需要删子记录,才行。那为啥级联不起作用了呢。
经过一番思考,原来必须用session.delete(object);这个语句才行,所以必须先查后删,这样hibernate才能根据主键记录找到要删的对象,并把many方先删除,再删one方。。
保存操作时,如果one many都是新建的,则必须这样进行关联:one.setMany(manyList),然后保存one方,这是最正确的方式。如果写many.setOne(one)并且session.save(many)则保存,说one方数据不是transient数据。如果many.setOne(One)并且session.save(one),则只保存one方数据。
如果one方数据是从数据库里查出来的,many为新建的,则可以many.setOne(one),再session.save(many)
(感觉是set的主动方是谁,一般要save这个主动方,否则关联关系进不来)
@Test/*有级联时,两个都是new的对象,用many方set one方保存one方,结果是只保存了one方*/
public void test111(){
Session session = HibernateUtil.getSession();
Dept dept = new Dept();
Emp emp1 = new Emp("张三");
emp1.setDept(dept);
session.save(dept);
session.beginTransaction().commit();
session.close();
}
Hibernate: insert into t_dept values ( )
@Test public void test10(){//最正确的写法,one.setMany()
Session session = HibernateUtil.getSession();
Dept dept = new Dept();
Emp emp1 = new Emp("张三");
Set<Emp> list = new HashSet<Emp>();
list.add(emp1);
dept.setEmps(list);
session.save(dept);
session.beginTransaction().commit();
session.close();
}
Hibernate: insert into t_dept values ( )
Hibernate: insert into t_emp (ename) values (?)
@Test public void test12(){//one方为数据库里已有的数据,many方为new的,可以many.setOne()再save(many)
Session session = HibernateUtil.getSession();
Dept dept = new Dept();
session.save(dept);
session.flush();
Emp emp1 = new Emp("张三");
emp1.setDept(dept);
session.save(emp1);---------------改为save(dept)或update(dept)都不行!!!只会单独保存dept!!set主动方是谁,就要保存它
session.beginTransaction().commit();
session.close();
}
Hibernate: insert into t_dept values ( )
Hibernate: insert into t_emp (ename, did) values (?, ?)
删除many方时,直接写session.delete();居然报错了。
ObjectDeleteException:deleted object would be re-saved by casade(remove deleted object from associations)
因为级联关系,无法删除many方,
解决办法是解除级联,如何解除呢?
可以感觉manY方取得one方对象,再取many集合列表将该many对象移除,在该many方设置one方为null.
thismany.getoneside().getManys().remove(thismany);
thisMany.setOne(null);
manyDao.delete(thisMany);
--------------------------------------------------------------------------------------------------------------------------------------------
映射文件中,<many-to-one>或<one-to-one>时,都会产生外键。
比如A表和B表,A和B是一对多的关系。
数据库底层建表时,A和B是两个独立的表,不存在外键,但映射文件有<many-to-one>什么的,产生外键,那么当one方找不到的时候,就会报异常,所以在one方要加not-found="ignore"来忽略。
如果,数据库建表时,A和B也明确指定外键了,映射文件是<many-to-one>,就不用加not-found="ignore",one方不存在时直接报null。