知识大全 hibernate级联删除

Posted

篇首语:人行千里路,胜读十年书。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 hibernate级联删除相关的知识,希望对你有一定的参考价值。

  有两张表 结构如下

  Java代码

  t_item                           t_bid

  id        int                     id        int

  name    varchar                   name      varchar

  item_id   int

  其中表t_item的主键id是表t_bid的item_id字段的外键 那么在这种情况下 如果删除表t_item中的记录 并且该记录中的id主键被t_bid中的item_id字段所引用 就会抛出如下异常

  Java代码

  ERROR ( ): Cannot delete or update a parent row: a foreign key constraint fails (`test/t_bid` CONSTRAINT `fk_id` FOREIGN KEY (`id`) REFERENCES `t_item

  ` (`id`))

  解决方法 级联删除 即在删除t_item表中的记录时同时删除t_bid表中的相关记录

  ( ) 增加外键约束时声明级联删除 即

  Java代码

  alter table t_bid add constraint fk_id foreign key(id) references

  key(id) on delete cascade

  ( ) 使用触发器 在删除t_item表中记录之前先删除与之相关的t_bid表中的记录

  触发器代码(MySQL)

  Java代码

  delimiter //

  create trigger tri_delete before delete on t_item

  for each row

  begin

  delete from t_bid where id = old id;

  end //

  Hibernate中的解决方案

  这个问题在Hibernate中相对容易解决 只需设置cascade = delete 即可 此时观察发出的sql语句

  Java代码

  Hibernate: select item _ id as id _ _ item _ name as name _ _ from t_item item _ where item _ id=?

  Hibernate: select em_id as item _ _ bids _ id as id _ bids _ id as id _ _ bids _ price as price _ _ em_id as item _ _ _ from t_bid bids _ where em_id=?

  Hibernate: update t_bid set item_id=null where item_id=?

  Hibernate: delete from t_bid where id=?

  Hibernate: delete from t_bid where id=?

  Hibernate: delete from t_item where id=?

  发现在删除t_bid表中记录之前会先将它的item_id字段值设置为null 但如果我们在映射文件中设置item_id字段不能为null 即设置Bid hbm xml文件为 Java代码

  <many to one name= item column= item_id class= po Item not null= true />

  注意不能在Item hbm xml文件中进行如下设置(即在key元素中指定not null= true )

  Java代码

  <set name= bids cascade= all >

  <key column= item_id not null= true />

  <one to many class= po Bid />

  </set>

  这样会抛出 Repeated column in mapping for entity 异常

  如果我们指定item_id字段值不能为null 那么在删除时会抛出如下异常

  Java代码

   hibernate exception GenericJDBCException: Could not execute JDBC batch update···

  Caused by: java sql BatchUpdateException: Data truncation: Column set to default value; NULL supplied to NOT NULL column item_id at row

  ???

  此时的解决方法是设置inverse= true 这在Hibernate文档中有相应的描述 Java代码

  Very Important Note: If the <key> column of a <one to many> association is declared NOT NULL Hibernate may cause constraint violations when it creates or updates the association To prevent this problem you must use a bidirectional association with the many valued end (the set or bag) marked as inverse= true

  观察此时发出的sql语句

  Java代码

  Hibernate: select item _ id as id _ _ item _ name as name _ _ from t_item item _ where item _ id=?

  Hibernate: select em_id as item _ _ bids _ id as id _ bids _ id as id _ _ bids _ amount as amount _ _ em_id as item _ _ _ from t_bid bids _ where em_id=?

  Hibernate: delete from t_bid where id=?

  Hibernate: delete from t_bid where id=?

  Hibernate: delete from t_item where id=?

  没有发出update语句 关于inverse= true 的理解

  save update: 级联保存(load以后如果子对象发生了更新 也会级联更新) 但它不会级联删除

  delete: 级联删除 但不具备级联保存和更新

  all delete orphan: 在解除父子关系时 自动删除不属于父对象的子对象 也支持级联删除和级联保存更新

  all: 级联删除 级联更新 但解除父子关系时不会自动删除子对象

  delete orphan:删除所有和当前对象解除关联关系的对象

  注意 以上设在哪一段就是指对哪一端的操作而言 比如delete 如果设在one的一端的<set>属性里 就是当one被删除的时候 自动删除所有的子记录

  如果设在many一端的<many to one>标签里 就是在删除many一端的数据时 会试图删除one一端的数据 如果仍然有many外键引用one 就会报 存在子记录 的错误 如果在one的一端同时也设置了cascade= delete 属性 就会发生很危险的情况 删除many一端的一条记录 会试图级联删除对应的one端记录 因为one也设置了级联删除many 所以其他所有与one关联的many都会被删掉

  所以 千万谨慎在many一端设置cascade= delete 属性

  故此cascade一般用在<one to one>和<one to many>中

  one to many中设置级联删除 比如:

  [x]

  <set

  name= entryvalues

  lazy= false

  inverse= true

  order by= VALUEID

  cascade= all delete orphan

  >

  <key>

  <column name= CONTEXTENTRYID />

  </key>

  <one to many

  class= Entryvalue

  />

  </set>

  如果用Hiberante的SchemaExport导出表到数据库 是不会在数据库中设置外键的cascade属性的 查看ENTRYVALUE表 其中的外键CONTEXTENTRYID的on delete属性是no action

  但是使用Hiberante管理事务 它是会维护这种级联关系的 比如这样操作:

  [java]

  public void testCascadeDelete()

  Session s = HibernateUtil getSession();

  Transaction tx;

  try

  tx = s beginTransaction();

  Contextentry ce = (Contextentry)s load(Contextentry class new Long( ));

  s delete(ce);

  mit();

   catch (HibernateException e)

  // TODO Auto generated catch block

  e printStackTrace();

  

  

  则引用此Contextentry的Entryvalue是会被正确级联删除的

  如果使用普通JDBC操作 比如:

  [java]

  public void testCascadeDeleteSQL()

  Session s = HibernateUtil getSession();

  Transaction tx;

  String sql = delete contextentry where id= ;

  try

  tx = s beginTransaction();

  Connection con = nnection();

  Statement st = con createStatement();

  st execute(sql);

  mit();

   catch (HibernateException e)

  // TODO Auto generated catch block

  e printStackTrace();

   catch (SQLException e)

  // TODO Auto generated catch block

  e printStackTrace();

  

  

  则会报 存在子记录 的错误 这里的Transaction实际上是无效的 因为用的是JDBC的Connection和Statement 已经脱离了Hibernate的管理 如果手动将ENTRYVALUE表的相关外键ON DELETE属性设为CASCADE 则上面的操作当然正确执行——级联删除子记录

  all delete-orphan 的能力

   当保存或更新父方对象时 级联保存或更新所有关联的子方对象 相当于 cascade 为 save update

   当删除父方对象时 级联删除所有关联的子方对象 相当于 cascade 为 delete

   删除不再和父方对象关联的所有子方对象 当然 不再和父方对象关联的所有子方对象 必须是在本次事务中发生的

  解除父子关系的 java 语句例如

  [java]

  public void testCascadeDelete()

  Session s = HibernateUtil getSession();

  Transaction tx;

  try

  tx = s beginTransaction();

  Contextentry ce = (Contextentry)s load(Contextentry class new Long( ));

  Entryvalue ev = (Entryvalue)s load(Entryvalue class new Long( ));

  ev setContextentry(null);

  s delete(ce);

  mit();

   catch (HibernateException e)

  // TODO Auto generated catch block

  e printStackTrace();

  

  

  如果 cascade 属性取默认值 null 当解除父子关系时 会执行如下 sql

  update ENTRYVALUE set CONTEXTENTRYID=null where ID=

cha138/Article/program/Java/ky/201311/28140

相关参考

知识大全 解析Oracle中多表级联删除的方法

解析Oracle中多表级联删除的方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!创建数据库时为了

知识大全 Hibernate批量更新与删除实例浅析

Hibernate批量更新与删除实例浅析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在我们的

知识大全 JPA和hibernate对删除操作的不同[1]

JPA和hibernate对删除操作的不同[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 JPA和hibernate对删除操作的不同[3]

JPA和hibernate对删除操作的不同[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 JPA和hibernate对删除操作的不同[5]

JPA和hibernate对删除操作的不同[5]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&n

知识大全 JPA和hibernate对删除操作的不同[4]

JPA和hibernate对删除操作的不同[4]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&n

知识大全 JPA和hibernate对删除操作的不同[2]

JPA和hibernate对删除操作的不同[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&n

知识大全 hibernate优化方案

  一批量修改和删除  在Hibernate中如果需要对任何数据进行修改和删除操作都需要先执行查询操作在得到要修改或者删除的数据后再对该数据进行相应的操作处理在数据量少的情况下采用这种处理方式没有问题

知识大全 介绍一下cascade(级联)

cha138/Article/program/Java/ky/201405/30838

知识大全 Oracle多表级联更新详解

Oracle多表级联更新详解  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!我们在平时的工作中可能遇