`
茴香豆
  • 浏览: 132524 次
  • 性别: Icon_minigender_2
  • 来自: 桂林
社区版块
存档分类
最新评论

hibernate的级联删除碰到的问题以及解决方法

阅读更多

      我们知道在处理hibernate的一对多的问题时,我们一般会在配置文件中写清它们的关系以及操作的规则。

      比如,在做网页时,会有博主和文章表,是一对多的关系。我用hiberbnate来实现它们的级联关系,配置文件如下

      博主Userinfo.hbm.xml代码如下:

 

<hibernate-mapping>
<!-- 指定类到表的映射 -->
    <class name="test.pojo.Userinfo" table="userinfo">
     <!--主键id的生成机制:native将自动根据数据库生成,mysql是自增长方式  -->
     <id name="id" column="id">
        <generator class="native"></generator>
     </id>
     <!--设定Userinfo类每个属性到userinfo表中对应列名的映射  -->
     <property name="name" column="name" />
     <property name="psw" column="psw"/>
     <property name="signature" column="signature"/>
     <property name="sex" column="sex"/>
     <property name="age" column="age"/>
      <property name="birthday" column="birthday"/>
     <property name="qq" column="qq"/>
     <property name="e_mail" column="e_mail"/>
     <property name="phone" column="phone"/>  
       <property name="occupation" column="occupation"/>
     <property name="score" column="score"/>
     <property name="graduateSchool" column="graduateSchool"/>
     <property name="country" column="country"/>
     <property name="province" column="province"/>
     <property name="head_path" column="head_path"/>
       <!--save-update  -->
     <!-- 映射Userinfo对象与Article对象的一对对多关系,以article方式映射 ,按id顺序排序,并延迟加载-->
     <bag name="articles" table="article" order-by="id asc" lazy="false" cascade="all-delete-orphan" >
     	<key column="userid"></key>
        <one-to-many class="test.pojo.Article"></one-to-many>
     </bag>    
       </class>
</hibernate-mapping>

  其实关键的一段是

 

 <bag name="articles" table="article" order-by="id asc" lazy="false" cascade="all-delete-orphan" >
     	<key column="userid"></key>
        <one-to-many class="test.pojo.Article"></one-to-many>
     </bag>    

 这一段实现对象与对象的级联关系

 

文章Article.hbm.xml代码如下:

 

<hibernate-mapping>
    <!--指定类到表的映射  -->
      <class name="test.pojo.Article" table="article">
    <!--主键id的生成机制:native将自动根据数据生成,mysql是自增长方式  -->
      <id name="id" column="id">
       <generator class="native"></generator>
      </id>
    <!--设定Article 类每个属性到article表中 对应列名的映射  -->
      <property name="title" column="title"></property>
      <property name="content" column="content"></property>
      <property name="publishTime" column="publishTime"></property>
      <property name="published" column="published"></property>
      <property name="clickCount" column="clickCount"></property>
      <property name="type" column="type"></property>
     
      <!--设定Article对象与Userinfo对象的多对一 关系 -->
     
 <many-to-one name="user" class="test.pojo.Userinfo" fetch="select" cascade="delete" outer-join="true">
      <column name="userid"/>
      </many-to-one>

     </class>
  </hibernate-mapping>

    关键的一段是

 

 <many-to-one name="user" class="test.pojo.Userinfo" fetch="select" cascade="delete" outer-join="true">
      <column name="userid"/>
      </many-to-one>

 

  这样写在测试时“增”,“改”,“查”是可以实现了,但是删除就不行。

 现在,我要把一个博主删掉,代码:

 Userinfo temuser=userDao.getUserinfoById(4);
  userDao.deleteUser(temuser);

 

 会报如下错误:

 

Hibernate: 
    select
        userinfo0_.id as id0_0_,
        userinfo0_.name as name0_0_,
        userinfo0_.psw as psw0_0_,
        userinfo0_.signature as signature0_0_,
        userinfo0_.sex as sex0_0_,
        userinfo0_.age as age0_0_,
        userinfo0_.birthday as birthday0_0_,
        userinfo0_.qq as qq0_0_,
        userinfo0_.e_mail as e9_0_0_,
        userinfo0_.phone as phone0_0_,
        userinfo0_.occupation as occupation0_0_,
        userinfo0_.score as score0_0_,
        userinfo0_.graduateSchool as graduat13_0_0_,
        userinfo0_.country as country0_0_,
        userinfo0_.province as province0_0_,
        userinfo0_.head_path as head16_0_0_ 
    from
        userinfo userinfo0_ 
    where
        userinfo0_.id=?
Hibernate: 
    select
        articles0_.userid as userid0_1_,
        articles0_.id as id1_,
        articles0_.id as id1_0_,
        articles0_.title as title1_0_,
        articles0_.content as content1_0_,
        articles0_.publishTime as publishT4_1_0_,
        articles0_.published as published1_0_,
        articles0_.clickCount as clickCount1_0_,
        articles0_.type as type1_0_,
        articles0_.userid as userid1_0_ 
    from
        article articles0_ 
    where
        articles0_.userid=? 
    order by
        articles0_.id asc
查询用户‘xiang'成功!
Hibernate: 
    update
        article 
    set
        userid=null 
    where
        userid=?
1953 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: 22001
1953 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Data truncation: Column was set to data type implicit default; NULL supplied for NOT NULL column 'userid' at row 1
1953 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.DataException: Could not execute JDBC batch update
	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:102)
	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:262)
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:180)
	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 org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
	at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
	at test.DAO.UserinfoDAO.deleteUser(UserinfoDAO.java:70)
	at test.test.TestUserinfo.main(TestUserinfo.java:25)
Caused by: java.sql.BatchUpdateException: Data truncation: Column was set to data type implicit default; NULL supplied for NOT NULL column 'userid' at row 1
	at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1213)
	at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:912)
	at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
	... 9 more
 

 这是为什么呢?

 

我们首先看它执行的sql语句,它为什么要update文章表呢?

 

 其实这跟hibernate的inverse有很大的关系,现在来看下inverse:

 下面是百度百科对inverse的解释

 

写道
Hibernate中的inverse在表关系映射中经常应用,
  inverse的值有两种,“true”和“false”。inverse="false"是默认的值,如果设置为true 则表示对象的状态变化不会同步到数据库 ;设置成false则相反;
  inverse的作用:在hibernate中是通过inverse的设置来决定是有谁来维护表和表之间的关系的。
  我们说inverse设立不当会导致性能低下,其实是说inverse设立不当,会产生多余重复的SQL语句甚至致使JDBC exception的throw。这是我们在建立实体类关系时必须需要关注的地方。一般来说,inverse=true是推荐使用,双向关联中双方都设置 inverse=false的话,必会导致双方都重复更新同一个关系。但是如果双方都设立inverse=true的话,双方都不维护关系的更新,这也是 不行的,好在一对多中的一端:many-to-one默认是inverse=false,避免了这种错误的产生。但是多对多就没有这个默认设置了,所以很 多人经常在多对多的两端都使用inverse=true,结果导致连接表的数据根本没有记录,就是因为他们双分都没有责任维护关系。所以说,双向关联中最 好的设置是一端为inverse=true,一端为inverse=false。一般inverse=false会放在多的一端,那么有人提问了, many-to-many两边都是多的,inverse到底放在哪儿?其实hibernate建立多对多关系也是将他们分离成两个一对多关系,中间连接一个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。
 

   其中还有一段时cascade和inverse的区别

 

写道
cascade定义的是关系两端对象到对象的级联关系;而inverse定义的是关系和对象的级联关系。
  inverse只对set+one-to-many(或many-to-many)有效,对many-to-one, one-to-one无效。cascade对关系标记都有效。
  inverse对集合对象整体起作用,cascade对集合对象中的一个一个元素起作用,如果集合为空,那么cascade不会引发关联操作。

 而在binernate的文档里也写有

 

写道
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".

所以要是在Userinfo.hbm.xml没设置inverse的话,它默认的是false,那么它就会把级联关系刷新,因为user_id是在

article表中设置,所以会出现user_id=null,所以会报错。

当在Userinfo.hbm.xml设置 inverse="true",它就不会再去更新级联关系,就可以直接进入数据库层面操作数据,所以上面删除用户时同时也把有级联关系的文章删掉了。

 

所以解决级联的“增删查改”问题,应该在“一对多”关系中的“一方”设置inverse=true;

 如:

 

<bag name="articles" table="article" order-by="id asc" lazy="false" cascade="all-delete-orphan" inverse="true">
     	<key column="userid"></key>
        <one-to-many class="test.pojo.Article"></one-to-many>
     </bag>    
 

这样就行了。

 

 

 

分享到:
评论

相关推荐

    关于Hibernate级联删除的问题.doc

    在文档中提到的场景下,我们来详细探讨Hibernate级联删除的原理和配置方法。 首先,我们要理解关系映射中的几个关键概念。在给出的例子中,有四个表:A、AA、B和BB,它们之间存在一对多(one-to-many)和一对一...

    hibernate 级联查询

    4. **级联查询示例**:例如,一个用户可以有多个订单,当删除用户时,如果设置了级联删除,那么相关的订单也会被一起删除。 5. **级联操作的优缺点**:优点是简化了代码,提高了开发效率;缺点是如果不合理使用,...

    hibernate many-to-many级联保存,级联更新,级联删除

    本文将深入探讨如何在Hibernate中处理Many-to-Many关系的级联保存、级联更新和级联删除。 一、Many-to-Many关系基础 在数据库设计中,Many-to-Many关系意味着两个实体之间存在多对多的关系。例如,学生可以选修多门...

    Hibernate的级联操作(增,删,该)

    2. 级联删除(Cascade Type.REMOVE) 当设置为`CascadeType.REMOVE`时,如果删除了父实体,与之关联的子实体也会被删除。这在处理一对多或者多对多关系时非常有用,可以确保相关的数据在数据库中得到一致性的清理。...

    Hibernate级联操作一对多demo

    通过这个" Hibernate级联操作一对多demo ",开发者可以深入理解如何在实际项目中利用Hibernate的级联功能来简化代码,提高开发效率,同时也要注意潜在的风险和性能问题。在实践中不断优化,才能更好地掌握这一强大的...

    hibernate级联增删改查

    首先,级联操作在Hibernate中是一种配置,用于指定当主表中的实体发生变化时,是否以及如何更新或删除关联的从表实体。级联操作可以通过在映射文件或注解中进行设置。例如,如果t_card是主表,而t_person是从表,...

    hibernate 级联(cascade和inverse)一对多

    反转主要用来解决关联关系的维护问题。在一对多关系中,通常有一端负责维护关联,另一端则不负责。反转(inverse)就是指将关联关系的维护权交给另一方。默认情况下,一端(通常是多的一端)负责维护关联,但如果...

    Hibernate的缓存级联查询

    在IT领域,尤其是在Java开发中,Hibernate是一个非常重要的对象关系映射(ORM)框架,它允许开发者用面向对象的方式操作数据库。尽管随着Spring Data JPA等现代技术的崛起,Hibernate的使用频率有所下降,但其核心...

    Hibernate_级联关系说明_-_关于cascade和inverse的用法

    在探讨Hibernate框架中的级联操作(cascade)与控制权反转(inverse)之前,我们需要先对Hibernate有一个基本的理解。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用提供了一种将对象模型映射到...

    Hibernate 一对多、多对一、级联、加载、反转

    5. **反转关系**:反转关系涉及到主从关系的反转,通常用于解决级联操作带来的问题。例如,如果在`User`和`Order`的关系中,我们希望由`User`来控制级联操作,可以将`@OneToMany`的`mappedBy`属性设在`User`上,然后...

    Hibernate级联操作.docx

    3. `save-update`:仅在执行 `save()`, `update()` 或 `saveOrUpdate()` 方法时级联。 4. `delete`:仅在执行 `delete()` 操作时级联。 例如,在 `Classes` 类的 `student` 集合中,设置 `cascade="save-update"` ...

    第七章_Hibernate_-_级联策略

    第七章_Hibernate_-_级联策略 第七章

    3.3、Hibernate级联关系(Av839011656,P3).mp4

    3.3、Hibernate级联关系(Av839011656,P3).mp4

    用hibernate做的省市县三级级联,

    总的来说,这个项目展示了如何使用Hibernate、Ajax和DWR来实现一个高效、用户友好的省市县三级级联选择功能。开发过程中涉及了ORM、MVC架构、数据库操作以及前端交互等多个方面,是学习和实践Web开发技能的好实例。

    Ajax+struts+hibernate实现级联菜单

    Ajax+struts+hibernate实现级联菜单 Ajax+struts+hibernate实现级联菜单 Ajax+struts+hibernate实现级联菜单

    Hibernate cascade (级联).doc

    ### Hibernate级联(Cascade)详解 #### 一、概述 Hibernate 是一款强大的对象关系映射 (ORM) 框架,它允许开发人员将 Java 对象模型映射到数据库表,从而极大地简化了数据访问层的开发工作。在 Hibernate 中,...

    hibernate3.2的级联关系_JavaProject

    级联关系在Hibernate中是指当一个实体发生某种操作(如保存、更新、删除)时,是否会影响到与之相关联的其他实体。通过配置级联关系,我们可以控制这些关联实体的行为。 1. **一对多(OneToMany)**:在数据库中,...

    74HC595 级联-时钟偏移问题.pdf

    * 可以通过调整时钟信号的频率和相位、使用缓冲器或反馈电路、使用差分信号传输技术等方法来解决时钟偏移问题。 * 了解 SN74HC595 的基本知识和时钟偏移问题的产生原因是设计和应用 SN74HC595 级联系统的关键。

    qt实现sqlite3级联删除demo

    在这个"qt实现sqlite3级联删除demo"中,开发者可能已经提供了完整的代码示例,包括创建表、插入数据、级联删除以及异常处理等。在VS2010 + Qt5.40 + Win7环境下,这个示例应该能够成功编译和运行。为了进一步学习和...

Global site tag (gtag.js) - Google Analytics