hibernate级联删除_第1页
hibernate级联删除_第2页
hibernate级联删除_第3页
hibernate级联删除_第4页
hibernate级联删除_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JPA 下的 Hibernate 实现一对多级联删除 5 Hibernate 级联问题 9 级联问题 11 hibernate 级联删除 问题之 inverse 配置 13 hibernate 级联删除 15 Hibernate 的组成的组成 1 SessionFactory 完整包名 org hibernate SessionFactory 用业创建 Session 类的实例 SessionFactory 是线程安全的 可以被多个线程并发调用 因此在实际应用中针对一个数据 库只创建一个该类的实例即可 2 Session 完整包名 org hibernate Session 用来操作数据库的各种方法 如 sava delete update createQuery 等 Session 是非线程安全的 每执行一个数据库事务 应创 建一个 Session 实际 3 Transaction 完整包 org hibernate Transaction 用来管理与数据库交互过程中的事务 4 ConnectionProvider 完整包 org hibernate connection ConnectionProvider 用于连接 JDBC 5 TransationFactory 完整包 org hibernate TransactionFactory 用来创建 Transation 实例的工 厂 它可以用来选择事务类型 其中包括 Hibernate 可以处理的 3 种事务类型 JDBC JTA 和 JNDI 6 Xml 格式的配置文件 hibernate cfg xml 开发时放在 src 下 发布后位于 WEB INF classes 目录下 主要内容 a show sql 是否输出 SQL 语句 b connection username 连接数据库的用户名 c connection password 连接数据库的密码 d connection url 连接数据库的 URl e Dealect 使用的连接数据库的方言 默认为 org hibernate dialect SQLServerDialect 即 SQL Server 数据库方言 f Connection driver class 用于驱动数据库的工具类 例如 java 中驱动 SQLServer 的工具类为 com microsoft jdbc sqlserver SQLServerDriver 7 Configuration 用于初始化 Hibernate 创建 SessionFactory 实例 在程序中 通过如下代 码创建 Configuration 类对象 Configuration config new Configuration 在实例化过程中 config 对象会首先读取 hibernate properties 文件 如果没有该属性文件 那么会加载 hibernate cfg xml 配置文件 并通过 configur 方法来读取配置文件 8 SessionFactory 通过 Configuration 类中方法创建 它用来初始化 Session 类 Hibernate 交 互数据库的工具类 当创建了 Configuration 类的对象后 就可以通过该类中的方法来创 建 SessionFactory 类了 应用 Hibernate 必须创建 SessionFactory 类 创建 SessionFactory 对 象的代码如下 SessionFactory session cfg buildSessionFactory 9 Session Hibernate 的动作 核心就是 Session 类 它负责管理对象的生命周期 事件处理 数据交互等 Session 类的创建代码如下 Session session sessionFactory openSession Session 类用来与数据库交互的常用方法包括 a Save 保存数据 该方法可以将数据存储到指定数据表当中 b createQuery 通过查询语句字符串来完成数据的查询操作 可以全部查询也可以 有条件的查询 c Load 根据 OID 对象标识 来加载数据库中指定的数据 d Update 根据 load 方法加载的数据与当前的数据比较 来更新数据表中的数据 e Delete 根据 OID 删除数据表中一条数据 f beginTransaction 获取事务管理对象 10 Hibernate 针对一对一的关联提供两个映射方法 a 按照主键映射 要求两个数据表以主键相关联 即其中一个表的 ID 字段既是主 键又是外键 两个表共享主键 b 外键映射 这种方式要求一个表中的主键关联另一个表中外键 即一个表中的外 键参照另一个表的主键 11 Hibernate 针对一对多的关联关系提供了以下映射方法 a 单向关联 在实体类中 将一的一方 如客户 定义为多的一方 如订单 的一个属性 在多的一方的映射文件中使用元素 b 双向关联 在实体类中 将一的一方 如客户 定义为多的一方 如订单 的一个属性 同时在一的一方定义一个集合型 Set 类型 的属性 在多的一方的映射文件中使用 元素 在一的一方的映射文件中使用元素及其子元素 12 Hibernate 针对多对多的关联提供以下映射方法 a 单向关联 在实体类中 其中任意一方定义一个集合类型 Set 类型 的属性 并在 其映射文件中使用元素及其子元素 b 双向关联 在实体类中 双方均定义一个集合类型 Set 类型 的属性 并在各自的 映射文件中使用元素及其子元素 13 Hibernate 工作步骤 a 读取并解析配置文件 这是使用 Hibernate 框架的入口 由 Configue 类创建 b 读取并解析映射信息 调用 Configue 中的 buildSessionFactory 方法来实现 同时 创建 SessionFactory c 开启 Session 调用 sessionFactory 的 openSession 方法来实现 d 创建事务管理对象 Transaction 调用 Session 对象的 beginTransaction 来实现 e 数据交互操作 调用 Session 对象的各种操纵数据库的方法来处理数据 如增 删 查 改操作 f 提交事务 完成了对数据库的操作后应该提交事务 完成一次事务处理 g 关闭 Session 结束了对数据库的访问以后 应该立即关闭 Session 对象 释放其 占用的内存 h 关闭 SessionFactory 完成了全部的数据库操作后关闭 SessionFactory 对象 1 对于一个简单的对于一个简单的 hibernate 中所依持的中所依持的 jar 2 这里需要八个 jar 1 在 hibernate distribution 3 6 8 Final 下找到 hibernate3 jar 2 在 hibernate distribution 3 6 8 Final lib required 全部的 jar 3 在 hibernate distribution 3 6 8 Final lib jpa 的 hibernate jpa 2 0 api 1 0 1 Final jar 这个 jar 是 sun 公司提供的 对于 hibernate 中通过注解来完成 javaBean 影射表的依赖包 通过它 hibernate 加强了通过注解 来完成 javaBean 影射表 连接数据库的驱动包连接数据库的驱动包 例 mysql connector java 5 1 17 bin jar 在 hibernate distribution 3 6 8 Final project etc 中有对于配置的模板 二 对于使用日志的二 对于使用日志的 hibernate 要在以上基础上增加两个 jar 这里需要注意 slf4j log4j12 1 6 4 jar 的版本 必须 要高于 slf4j api 1 6 1 jar 1 在 slf4j 1 6 4 中的 slf4j log4j12 1 6 4 jar 这个 jar 不是 hibernate 的 而是 slf4j 1 6 4 的 2 在 apache log4j 1 2 16 zip 下的 log4j 1 2 16 jar 这个 jar 不是 hibernate 的 而是 apache 的 log4j 需要一个配置文件即 classpath log4j properties 为什么要使用为什么要使用 log4j 为了更加详细的看到 hibernate 的启动过程 在 hibernate distribution 3 6 8 Final lib required 中有这样一个 slf4j api 1 6 1 jar 它不是日志 包 它是一个中间的日志转换器 日志相关日志相关 jar commons logging log4j jboss logging 1 对于 log4j 所需要的 log4j properties 详细注释 定义日志文件的输出级别和目标 级别 一般是五个 on 全部输出 debug info warn error Fatal off 关闭 三大组件 logger 日志 appender 目标 layout 格式 stdout 输入目标到控制台 file 输入目标到本地 log4j rootLogger debug stdout file org apache log4j ConsoleAppender 指定是控制台输出 System out 指定是 system out 打印语句 也可以是 system err log4j appender stdout Target System out org apache log4j PatternLayout 指定格式 d yyyy MM dd HH mm ss SSS 5p c L m n 指定具体的输出格式 d 日期格式 SSS 毫秒 p 级别 5p 格式调整为五位 c class 类名 L line 行号 m message 信息 n n 换行 log4j appender stdout org apache log4j ConsoleAppender log4j appender stdout layout org apache log4j PatternLayout log4j appender stdout layout ConversionPattern d yyyy MM dd HH mm ss SSS 5p c L m n org apache log4j FileAppender 指定是输出到本地文件 d logs root log 指定输出到本地的具体位置 log4j appender file MaxFileSize 64KB 指定日志文件的最大值 log4j appender file MaxBackupIndex 3 指定日志文件备份多少个 org apache log4j PatternLayout 指定格式 d yyyy MM dd HH mm ss SSS 5p c L m n 指定具体格式 d date p proritiy 级别 c class L line m message n d yyyy MM dd HH mm ss SSS 5p c L m n 指定具体的输出格式 d 日期格式 SSS 毫秒 p 级别 5p 格式调整为五位 c class 类名 L line 行号 m message 信息 n n 换行 log4j appender file org apache log4j FileAppender log4j appender file File d logs root log log4j appender file MaxFileSize 64KB log4j appender file MaxBackupIndex 3 log4j appender file layout org apache log4j PatternLayout log4j appender file layout ConversionPattern d yyyy MM dd HH mm ss SSS 5p c L m n 2 对于 log4j 所需要的 log4j properties 的不带注释的 log4j rootLogger INFO sd file log4j appender sd org apache log4j ConsoleAppender log4j appender sd layout org apache log4j PatternLayout log4j appender sd layout ConversionPattern d yyyy MM dd HH mm ss SSS 5p c L m n log4j appender file org apache log4j RollingFileAppender log4j appender file File d logs root log log4j appender file MaxFileSize 64KB log4j appender file MaxBackupIndex 3 log4j appender file layout org apache log4j PatternLayout log4j appender file layout ConversionPattern d yyyy MM dd HH mm ss SSS 5p c L m n 三 对于三 对于 hibernate 使用使用 c3p0 连接池连接池 对于一次创建多少连接的问题 一般是三分之一原则 例如有 1000 人访问 要创建多少连接 300 最好说是 130 到 200 之间 因为这样就代 表你了解这个 当说 130 到 200 后你还要说这个要通过优化代码来实现就是当用完这个连接后一定要 立刻返回到连接池也就是让连接交互使用 这里需要一个 jar 在 hibernate distribution 3 6 8 Final lib optional c3p0 下的 c3p0 0 9 1 jar 1 hibernate 对于 c3p0 的配置 在 hibernate properties 中 C3P0 Connection Pool hibernate c3p0 max size 2 最大连接数 hibernate c3p0 min size 2 初始值 hibernate c3p0 timeout 5000 连接超时时间 5 秒 hibernate c3p0 max statements 100 每次批处理的最大数量 hibernate c3p0 idle test period 3000 最大空闲时间 3 秒 hibernate c3p0 acquire increment 2 当连接不足时 一次创建多少个 hibernate c3p0 validate false 验证 2 hibernate 对于 c3p0 的配置 在 hibernate cfg xml 中 4 2000 2 2 四 四 hibernate 使用二级缓存使用二级缓存 需要第三方包 ehcache 2 4 4 distribution ehcache 2 4 4 lib ehcache core 2 4 4 jar 加入到 classpath 中 还有一个日志包 当在二中配置了日志包后 就不需要再配置了 这里还要将 ehcache xml 文件放到 classpath 根目录下 ehcache xml 文件的配置 Hibernate 实现级联删除实现级联删除 一 一 我的使用背景 有新闻和新闻类型 一条新闻只能属于一个类型 一种新闻类型可以对应多条新闻 在数据库中 新闻受新闻类型外键约束 并可以级联删除 在 Hibernate 中 实现级联删除 一 创建数据库表和关系 DROP TABLE NewsType CREATE TABLE NewsType TypeID NUMBER 10 PRIMARY KEY NOT NULL TypeName VARCHAR2 400 NOT NULL DirName VARCHAR2 400 NOT NULL TemplateName VARCHAR2 400 NOT NULL DROP SEQUENCE NEWSTYPE SEQ CREATE SEQUENCE NEWSTYPE SEQ INCREMENT BY 1 START WITH 1 DROP TABLE News CREATE TABLE News NewsID NUMBER 10 PRIMARY KEY NOT NULL TypeID NUMBER 10 NOT NULL Title VARCHAR2 400 NOT NULL HitCount NUMBER 10 DEFAULT 0 NOT NULL IssuseDate DATE NOT NULL DeployerID NUMBER 10 NOT NULL Origin VARCHAR2 400 NOT NULL URL VARCHAR2 400 NOT NULL KEYWORDS VARCHAR 400 Priority NUMBER 10 DEFAULT 0 NOT NULL Special VARCHAR2 400 Description VARCHAR2 400 Author VARCHAR2 400 Topic VARCHAR2 400 DROP SEQUENCE NEWS SEQ CREATE SEQUENCE NEWS SEQ INCREMENT BY 1 START WITH 1 在 oralce 中 设置数据表的约束关系如下图 二 实现数据表到 POJO 的映射 映射类 我们略去 此处主要显示配置文件 News hbm xml NEWS SEQ Newstype hbm xml 其实这是个双向以对多关系 三 在 DAO 中实现级联删除 删除新闻类型记录 dao getNewsTypeDAO deleteObjects typeIDs typeID 是新闻类型的主键 执行此操作将会删除所有此新闻类型的新闻 news 是一个 Set 类型的变量 用来存放此类型的所有的新闻 四 删除时遇到的问题 在数据库中 如果设置了约束关系 那么一定要允许级联删除 否则 你在执行删除时会抛出异常 如果我们的数据库关系设置如下 画圈的那个选项没有选上的话画圈的那个选项没有选上的话 那么我们在执行的时候就会抛出如下的异常 006 04 06 13 20 16 ERROR http 8080 Processor23 JDBCExceptionReporter java 72 ORA 02292 违反完整约束条件 SC NEWS TYPE RELATIONS 已找到子记录日志 rg hibernate exception ConstraintViolationException could not execute update q ery at org hibernate exception SQLStateConverter convert SQLStateConverter j va 69 at org hibernate exception JDBCExceptionHelper convert JDBCExceptionHelp r java 43 at org hibernate hql ast exec BasicExecutor execute BasicExecutor java 8 问题的关键在如下两点 1 数据库中要允许数据表的级联删除 2 在映射文件中要将级联删除配置正确 JPA 下的下的 Hibernate 实现一对多级联删除实现一对多级联删除 再谈 Hibernate 级联删除 JPA 下的 Hibernate 实现一对多级联删除 CascadeType DELETE ORPHAN 声明 1 本文系原创 非抄袭或转载过来的 2 本文论点都亲手做过实验论证 3 本文所讲的 Hibernate 配置都基于注解的方式 hbm 语法未提供 很多人对持久层概念搞不清 JPA Hibernate EJB3 0的关系 这里做一下简单的说明 JPA 是一个持久层 设计接口 EJB3 0和 Hibernate 是具体的实现类 EJB3 0和 Hibernate 的功能近似相等的 Hibernate 没有 Session Bean Spring MVC3的 SessionAttribute 跟 Session Bean 近似 理论是使用 JPA 接口可以无缝切换持久层实现 但是仅仅是理论上 JPA 是在 Hibernate 成熟并大行其道的时候才推出的 基本上是借鉴 Hibernate 的优点 做了一个统一的标 准而已 JPA1 0没有一对多的级联删除配置 也许 JPA2 0里才有吧 这里没做过调研 OneToMany mappedBy commentTeam Cascade org hibernate annotations CascadeType SAVE UPDATE org hibernate annotations CascadeType DE LETE ORPHAN private Set commentTeamMembers 这里为了说明 只贴出一对多的关键代码 其它无关的注解已忽略掉 以免造成干扰 这里重点说明一下四个常用的注解配置的区别 CascadeType SAVE UPDATE CascadeType ALL CascadeType DELETE CascadeType DELETE ORPHAN 之所有之列出这四个 是因为我不想跟书本上把所有的概念都罗列出来 基本上开发时其中的3个都以及 足够用了 下面我结合代码演示一下他们之间的区别 以及使用的时候注意的地方 CascadeType SAVE UPDATE Hibernate 专有的 JPA 并不支持 作用是级联保存 级联更新 注 JPA 很恶心 要么你配置 CascadeType ALL 要么你配 CascadeType SAVE CasadeType Merge 八卦一句 专家虽牛 多年不写代 码 定的标准让编码麻烦呀 CascadeType ALL 级联保存 修改 删除 同步 一般很少用 看看控制台的一长串 SQL 就知道性能低 下 你没改的关联表也给你发 update 语句 我从来没用过这个属性 CascadeType DELETE 当调用 session delete A 的时候 级联删除关联的对象 注 先调用 A setB null 再调用 session delete A 这样是级联删不掉 B 的 CascadeType DELETE ORPHAN 一对多级联删除 下面重点来说说这个 CascadeType DELETE ORPHAN 看过 API 开发指南 级联删除就一个经典的 OneToMany mappedBy commentTeam Cascade CascadeType SAVE UPDATE CascadeType DELETE ORPHAN private Set commentTeamMembers mappedBy 不可少 映射 A B 一对多的另一边控制反转 谁控谁的问题 新版的 Hibernate3 4中配置更 简单 变一句了 更简洁吧 OneToMany mappedBy commentTeam orphanRemoval true private Set commentTeamMembers 以上两种配置方式是等价的 下面是在实际开发中的使用了 有些时候代码方面不注意 会误以为明明配 置正确了 但为什么不起作用呢 下面例举一下代码 请看 Action 代码 实际上我在 Spring Controller 里 N 年不写 DAO 了 Service 很少用 Manager 一边去 CommentTeam commentTeam this getHibernateTemplate get CommentTeam class id commentTeam setCommentTeamMember null 想级联删除子表数据 this getHibernateTemplate saveOrUpdate commentTeam 这样级联删除却没有发生 为什么呢 再来一个例子 CommentTeam commentTeam this getHibernateTemplate get CommentTeam class id Set commentTeamMembers new HashSet commentTeam setCommentTeamMember commentTeamMembers 想级联删除子表数据或增减替换对象 this getHibernateTemplate saveOrUpdate commentTeam 这个例子级联删除的效果也没发生 即使 commentTeamMembers 理由有若干个对象 成功执行级联删除的语法 CommentTeam commentTeam this getHibernateTemplate get CommentTeam class id commentTeam getCommentTeamMember clear 注意这里引用的集合还是原理的集合 这里没有重新 new 过 commentTeam getCommentTeamMember add new CommentTeamMember 如果想替换为新的集合可以用 addAll 方法 this getHibernateTemplate saveOrUpdate commentTeam 分析一下原因 级联删除起作用的前提是关联的集合对象不能重新指向新的引用 必须在原有的集合里操 作新增 删除 清空元素 像上面的 setXXX null 的方法等是起步到级联删除作用的 大概是 Hibernate 自认自己原生的集合对象吧 自己 New 的放进行级联删除无效 java view plaincopy Hibernate 级联问题级联问题 Hibernate 级联删除 tenyo 删除某一条数据 则其子表的所有级联数据全部自动删除 这样的需求在 Hibernate 里可以使用 cascade 简单地加以实现 下面就 Hibernate 级联删除的 问题举例进行说明 比如有下面四个表 比如有下面四个表 A id name AA id name a id B id name a id BB id name b id 假设它们之间的关系是 假设它们之间的关系是 A AA one to many A B one to one 外键定义 one to one 关系 B BB one to many A hbm xml B hbm xml 代码 代码 A a session getTransaction begin session delete a session getTransaction commit 这样 就会把 AA B BB 里相关数据自动删除 说明 说明 设置设置 Hibernate 级联删除 只需 级联删除 只需 1 在父端的 one to one many to one 关系 设置 cascade delete 或 cascade all 2 在父端的 one to many 关系 map set list bag 设置 cascade all delete orphan 或 cascade all 即可 级联问题 级联问题 有用户和用户组两个表 需要使用 hibernate 做级联删除 映射文件如下 Groups hbm xml html view plaincopyprint User hbm xml html view plaincopyprint 原本要做的是 删除用户组时将其下所属的用户全部删除 删除用户时 不对用户组进行更改 结果过执行报错 deleted object would be re saved by cascade removedeleted object from associations 感觉可能是 cascade 的配置问题 修改了下发现还是报错 后来我将 Groups 映射文件中元素的 lazy 属性设置为 true 删除成功 但是这样由于是延迟加载 就没法在页面中通过 groups 来获取 User 集合中 的对象了 本来是想统计用户组中用户成员的个数 于 是还得修改 查了文档弄明白了怎么回事 原来 cascade 属性在 lazy true 的时候不起作用 集合中对象还没初始化 所以在删除 User 的时候 就不 会触发对关联关系的维护 而当 lazy false 的时候 由于我们设置了 cascade 那么删除 User 的时候会触发关系维护 此时虽然在 user 中已经将对应的 Groups 属性设置为 null 删除前会先将外键设置为 null 但是由于 Groups 中的 Set 中仍然还保持着我们删除的 User 对象 所以触发关 系维护的时候 这个 User 对象又会被重新保存到数 据库中 造成了前面出现的异常 当然 如果我们删除 Groups 的时候 如果没有将 Set 的 cascade 设置为 all 或 delete 那么就会报错 Cannot delete or update a parent row a foreign key constraint fails 因为 groups 删除了 User 中对 groups 的外 键引用怎么办 解决的办法就是 如果不需要在 groups 中直接获取 Set 中的 User 对象 那么就把 lazy 设置为 true 就可以 了 不设置 cascade 也可以 不过删除 groups 的时候就可能有问题了 或者通过代码 在删除之前将关联 关系解除 public void delete User entity entity getGroups getUsers remove entity entity setGroups null userDao delete entity hibernate 级联删除级联删除 问题之问题之 inverse 配置配置 HibernateJavaBeanXMLSQL 今天写个级联删除始终报错 Could not execute JDBC batch update 后来发现是 calsses hbm xml 中的 inverse false 主控方 的原因 将它改为 inverse true 被控方 后就 ok 了 inverse 为 false classes 就要 维护 student 在执行删除时会 update 关联的 student 设置其 classid 但 classid 为 null 如果 studnet 表中 的 classid 为非空则会出以上异常 下面是代码 calsses hbm xml studeng hbm xml delete 方法 Override public void delete Classes classes sessionFactory getSessionFactory Session session sessionFactory openSession session setFlushMode FlushMode AUTO session beginTransaction begin session delete classes session beginTransaction commit session close sessionFactory close hibernate 级联删

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论