`
sunnyhl
  • 浏览: 79348 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多
需求描述:
  系统更新日志功能,需要在一个页面里展示主表信息+对所所有子表信息。

原始结构:
/**
 * 
 */
package common.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * 系统更新说明
 * 
 * @author sunhl
 *
 */
@Entity
@Table(name="T_CHANGELOG")
@DomainModel(name="系统更新")
public class ChangeLog extends AbstractModel implements Serializable {

	private static final long serialVersionUID = 1L;
	
	private String title; // 标题
	private List<ChangeLogItem> items = new ArrayList<ChangeLogItem>(); //详细内容
	
	//gets and sets
	
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
		
	@OneToMany
	public List<ChangeLogItem> getItems() {
		return items;
	}
	
	public void setItems(List<ChangeLogItem> items) {
		this.items = items;
	}

	public void addItem(ChangeLogItem item){
		this.getItems().add(item);
		item.setChangeLog(this);
	}
}
------------
/**
 * 
 */
package common.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;


/**
 * 系统更新详细内容
 * 
 * @author sunhl
 *
 */
@Entity
@Table(name="AI_CHANGELOG_ITEM")
@DomainModel(name="系统更新详情")
public class ChangeLogItem extends AbstractModel implements Serializable {

	private static final long serialVersionUID = 1L;

	private ChangeLog changeLog; //所属更新说明	
	private String content; //内容	
	
	//--
	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name="changeLog_id")
	public ChangeLog getChangeLog() {
		return changeLog;
	}
	public void setChangeLog(ChangeLog changeLog) {
		this.changeLog = changeLog;
	}
		
	@Column(length=2000)
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}

}




问题:

1- 级联提交需要的标记。
ChangeLog:
@OneToMany(cascade = CascadeType.ALL,mappedBy="changeLog")
public List<ChangeLogItem> getItems() {
    return items;
}

cascade:
级联操作的类型,{[CascadeType.PERSIST(级联新建)][,CascadeType.REMOVE(级联删除)][,CascadeType.REFRESH(级 联刷新)][,CascadeType.MERGE(级联更新)]},或者使用CascadeType.ALL,表示选择全部。
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="changeLog_id") //外键
public ChangeLog getChangeLog() {
		return changeLog;
}


2- 级联提交后子表无主表id
   完成1中设置后发现可以级联提交,但提交后changeLogItem的changeLog_id为空。
这是由于使用@OneToMany(mappedBy="changeLog")标记后系统将不再负责两个对象的关联问题,所以需要通过新建方法,给item自加设置changeLog属性的值。
//给新添加的item设置changeLog的值。
        public void addItem(ChangeLogItem item){
		this.getItems().add(item);
		item.setChangeLog(this);
	}


此时可以完成带子项的添加操作,但添加完成后需要展示详细内容时出现“net.sf.json.JSONException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.bnm.system.domain.SysMenu.childs, no session or session was closed ”的错误。

3- 在加载主表信息时把子表信息同时加载出来,所以需要添加(或修改FetchType.LAZY)fetch=FetchType.EAGER强抽即时加载子项。
@OneToMany(fetch=FetchType.EAGER,cascade = CascadeType.ALL,mappedBy="changeLog")
public List<ChangeLogItem> getItems() {
    return items;
}

fetch: FetchType.LAZY 延迟加载;FetchType.EAGER 即时加载。

完成后发现可以正常显示,并同时添加多条子项。
但回到changeLog列表发现,出现多条相同数据,changeLog的重复个数跟其子项数量是一致的。

4- 提交后主表列表出现多条相同记录。这是由于使用FetchType.EAGER加载子项时系统默认使用了left join的查询方式。另外,在本例中列表页面不需要显示子项信息,故将FetchType.EAGER改回FetchType.LAZY,在用户需要展开详情时再通过一次查询完成加载所有内容。
@OneToMany(fetch=FetchType.LAZY,cascade = CascadeType.ALL,mappedBy="changeLog")
public List<ChangeLogItem> getItems() {
    return items;
}
-------------------------------------------------
//在action中添加,视具体操作而定。
public void onEdit(){
    changeLogService.refash(changeLog)。
}


至此已可以正常显示列表和详情。
5- 无法新增的问题。新增时又出现“org.hibernate.AssertionFailure: null identifier”的问题。
故需要添加一个非空判断
public void onEdit(){
 if(changeLog.getId()!=null){   
     changeLogService.refash(changeLog)
  }
}

ok,至此主从表的关联操作已基本完成。

6- 无法单独删除子项的问题。
问题可能是特殊的,在详细信息中删除一个子项时我使用了remove(item)方法,完成后看似确实生效了,但当重新加载对应的数据时,刚才被删掉的子项又显示了出来。
修改方式是添加@Cascade (org.hibernate.annotations.CascadeType.DELETE_ORPHAN)标记 
//注:新添加的CascadeType.DELETE_ORPHAN是org.hibernate.annotations的标记。
// 而CascadeType.ALL是javax.persistence.CascadeType的

@OneToMany(fetch=FetchType.LAZY,cascade = CascadeType.ALL,mappedBy="changeLog")
@Cascade (org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
public List<ChangeLogItem> getItems() {
    return items;
}


终于完成。

------
关于第6个问题参考文档,内有详细说明:
http://blog.csdn.net/zhh521125/archive/2010/10/20/5954137.aspx
分享到:
评论

相关推荐

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

    在Hibernate中,级联操作(Cascading Operations)是一种高级特性,它使得对象之间的关联关系在数据库层面得以同步更新。当我们对一个实体对象进行操作时,可以设置级联属性,让这些操作自动传播到与之相关联的其他...

    javascript 下拉框 级联操作

    在本案例中,我们将深入探讨如何使用JavaScript实现下拉框的级联操作。 首先,我们需要理解HTML结构。通常,两个级联的下拉框会分别定义为`&lt;select&gt;`元素,并通过`id`属性来唯一标识它们。例如: ```html 选项1 ...

    JPA中的一对多双向关联与级联操作

    这篇博客将深入探讨JPA中的一对多双向关联以及级联操作。 首先,让我们理解一对多关联。假设我们有两个实体,一个是`User`(用户)和一个是`Post`(帖子)。一个用户可以发布多个帖子,但一个帖子只能属于一个用户...

    hibernate基础 二 关联映射 级联操作

    ### Hibernate基础之关联映射与级联操作 #### 第一部分:主键生成策略与对象状态管理 ##### 主键生成策略 在使用Hibernate框架时,合理的主键生成策略能够极大地简化开发工作并提升应用性能。Hibernate提供了多种...

    74HC595级联操作

    **74HC595级联操作** 74HC595是一款常见的数字集成电路,用于数据存储和串行到并行转换。它被广泛应用于LED显示、数码管驱动和其他需要扩展输出位数的场合。这款芯片包含8个D型触发器,能够存储8位二进制数据,并...

    Hibernate级联操作一对多demo

    在Java持久化框架Hibernate中,级联操作是处理对象关系映射(ORM)时非常重要的一个特性。级联操作允许我们在对一个实体进行操作时,自动地影响与之相关的其他实体,无需显式地处理这些关联。在这个" Hibernate级联...

    带CheckBox和级联操作的Tree

    带CheckBox和级联操作的Tree 带CheckBox和级联操作的Tree 带CheckBox和级联操作的Tree

    10_JPA详解_JPA中的一对多双向关联与级联操作.zip

    本资料包"10_JPA详解_JPA中的一对多双向关联与级联操作.zip"聚焦于JPA中的一个重要概念——一对多双向关联及其级联操作。以下是对这一主题的详细阐述。 **一对多关联** 在关系数据库设计中,一对多关联是最常见的...

    Compiere窗口级联操作图解

    在Compiere中,窗口级联操作是数据管理的一个重要特性,它允许用户在一个窗口中操作的数据会影响到关联的其他窗口或表中的数据,实现了数据的联动更新和一致性。在本例中,我们将探讨如何通过建表语句来实现这种级联...

    Hibernate级联操作.docx

    在 Hibernate 中,级联操作(Cascade)和反向属性(Inverse)是管理对象关系的重要概念,特别是在处理一对多(One-to-Many)或多对一(Many-to-One)关系时。 **级联操作(Cascade)** 级联操作定义了当主对象被...

    10_传智播客JPA详解_JPA中的一对多双向关联与级联操作

    本教程将深入探讨JPA中的一对多双向关联及级联操作,这对于理解和使用JPA进行复杂数据模型管理至关重要。 首先,我们来理解一下一对多关联。在数据库设计中,一对多关联是指一个实体(表)可以与多个其他实体相关联...

    用Struts2+Spring+Hibernate三大框架完成的级联操作

    本项目通过这三大框架实现了一个级联操作,具体涉及到了省市县以及年月日的选择,这种级联下拉菜单在实际应用中常常用于地址填写或日期选择等场景。 Struts2是基于MVC设计模式的Web框架,主要负责处理用户的请求和...

    jquery实现级联操作

    在Web开发中,级联操作通常指的是一个下拉列表(Dropdown)的选择会影响到另一个下拉列表的选项,这种交互效果能够帮助用户更有效地过滤和选择数据。在这个场景中,我们将使用jQuery来实现这样的功能,结合JSP(Java...

    SSH+JQuery+MySQL级联操作(省市县级联)

    在这个“SSH+JQuery+MySQL级联操作(省市县级联)”的案例中,我们将深入探讨如何利用这些技术实现一个省市县三级联动的效果。 首先,让我们了解什么是级联操作。级联操作通常指的是在一个选择发生变化时,相关的...

    C# 省市区的级联操作

    在这个场景中,我们关注的是使用C#编程语言,配合SQL Server数据库,来实现省市区的级联操作。这种功能常见于地址输入、物流配送等需要逐级选择地区信息的系统。 首先,我们需要理解C#在后台处理中的角色。C#是.NET...

    AngularJS级联操作

    在AngularJS中,级联操作通常涉及到数据的深度绑定和组件间的交互,特别是在构建复杂的用户界面时。这个概念尤其有用,比如在实现下拉菜单、树形结构或者联动选择器等场景。在这个“AngularJS两级”主题中,我们将...

    框架[Hibernate]利用Hibernate进行一对多的级联操作-Web实例 java

    【框架】[Hibernate]利用Hibernate进行一对多的级联操作-Web实例 java

    下拉菜单的级联操作(ajax)

    在开发中常常会遇到菜单的级联操作,比如:国家、城市、乡镇的选择等。当选中某个国家的时候,后面的菜单会把该国家内的城市罗列出来,当选中城市的时候,后面的菜单会把对应的乡镇列出来。  解决这种菜单的级联...

Global site tag (gtag.js) - Google Analytics