您的位置:首页 > 其它

Hibernate级联保存与删除

2016-03-19 17:56 253 查看
Hibernate为程序员提供一种级联操作,在编写程序时,通过Hibernate的级联功能可以很方便的操作数据库的主从表的数据,我们最常用的级联是级联保存和级联删除,下面分别来看一下级联保存和级联删除。

我准备了MenuPanel和Menu两个对象,先来看一下两个对象的关系



从上图可以看出,MenuPanel和Menu是一对多的关系,Menu表同时存在多个子节点,用parentId代表该节点的父节点。

在JPA中,配置级联操作我们可以用cascade=CascadeType.ALL,意思是支持所有的级联操作,网上有很多文章说级联保存用CascadeType.PERSIST,这也是可以的,我们分别在代码中使用以上两个类型。在MenuPane的getChildren()方法中标上下面的注解:

@OneToMany(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY,mappedBy="menu")
public List<Menu> getChildren() {
return children;
}


在Menu的getChildren()的方法中标上下面的注解

@OneToMany(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY,mappedBy="menu")
public List<Menu> getChildren() {
return children;
}


以上代码实现级联保存的配置,我们需要在业务逻辑中为对象设置关系,这样Hibernate才能自动实现级联保存,如果只是配置了级联操作,而没有在对象中设置对象之前的关系,Hibernate是无法实现级联保存的功能的。

首先实例化MenuPanel

MenuPanel panel1 = new MenuPanel("基础设置");


再实例化几个Menu

Menu menuCard=new Menu("会员卡设置","");
menuCard.setLeaf(false);
Menu menu1 = new Menu("卡类型设置", "basicOperation/queryCardType");
Menu menu2 = new Menu("站点设定", "basicOperation/querySite");
Menu menu3 = new Menu("操作员授权", "basicOperation/queryOperatorSet");
Menu menu4 = new Menu("密码修改", "test.do");
Menu menu5 = new Menu("消费项目管理", "test1.do");

我们要把menuCard作为menu1的父节点,故作如下设置

List<Menu> cardChildMenus=new ArrayList<Menu>();
cardChildMenus.add(menu1);
menuCard.setChildren(cardChildMenus);//把卡类型设置作为会员卡设置的子菜单


设置对象之间的关系,这一步很关键,直接影响保存结果

menu1.setMenu(menuCard);//为会员卡设置设置卡类型设置,以支持级联保存
menuCard.setMenuPanel(panel1);
//设置Menu属于MenuPanel
menu2.setMenuPanel(panel1);
menu3.setMenuPanel(panel1);
menu4.setMenuPanel(panel1);
menu5.setMenuPanel(panel1);

//将Menu添加到MenuPanel
panel1.getMenus().add(menuCard);
panel1.getMenus().add(menu2);
panel1.getMenus().add(menu3);
panel1.getMenus().add(menu4);
panel1.getMenus().add(menu5);


具体代码:

@Override
public boolean testAdd() {
List<MenuPanel> menuPanels=new ArrayList<MenuPanel>();

MenuPanel panel1 = new MenuPanel("基础设置");
Menu menuCard=new Menu("会员卡设置","");
menuCard.setLeaf(false);

Menu menu1 = new Menu("卡类型设置", "basicOperation/queryCardType");
Menu menu2 = new Menu("站点设定", "basicOperation/querySite");
Menu menu3 = new Menu("操作员授权", "basicOperation/queryOperatorSet");
Menu menu4 = new Menu("密码修改", "test.do");
Menu menu5 = new Menu("消费项目管理", "test1.do");

menu1.setMenu(menuCard);//为会员卡设置设置卡类型设置,以支持级联保存
menuCard.setMenuPanel(panel1);

menu2.setMenuPanel(panel1);
menu3.setMenuPanel(panel1);
menu4.setMenuPanel(panel1);
menu5.setMenuPanel(panel1);

List<Menu> cardChildMenus=new ArrayList<Menu>(); cardChildMenus.add(menu1); menuCard.setChildren(cardChildMenus);//把卡类型设置作为会员卡设置的子菜单
panel1.getMenus().add(menuCard);
panel1.getMenus().add(menu2);
panel1.getMenus().add(menu3);
panel1.getMenus().add(menu4);
panel1.getMenus().add(menu5);

MenuPanel panel2 = new MenuPanel("日常操作");
Menu menu10 = new Menu("发行新卡", "operate/cardList?type=add");
Menu menu11 = new Menu("存款入卡", "operate/cardList?type=depositMoney");
Menu menu12 = new Menu("卡中取款", "operate/cardList?type=drawMoney");
Menu menu13 = new Menu("奖品管理", "operate/cardList?type=prize");
Menu menu14 = new Menu("卡挂失", "operate/cardList?type=reportLoss");
Menu menu15 = new Menu("卡解挂", "operate/cardList?type=cancelLoss");
Menu menu16 = new Menu("并卡", "operate/cardList?type=mergeCard");
Menu menu17 = new Menu("补办新卡", "operate/cardList?type=mendCard");
Menu menu18 = new Menu("回收旧卡", "operate/cardList?type=recycleCard");
Menu menu19 = new Menu("维护", "operate/cardList?type=maintain");

menu10.setMenuPanel(panel2);
menu11.setMenuPanel(panel2);
menu12.setMenuPanel(panel2);
menu13.setMenuPanel(panel2);
menu14.setMenuPanel(panel2);
menu15.setMenuPanel(panel2);
menu16.setMenuPanel(panel2);
menu17.setMenuPanel(panel2);
menu18.setMenuPanel(panel2);
menu19.setMenuPanel(panel2);

panel2.getMenus().add(menu10);
panel2.getMenus().add(menu11);
panel2.getMenus().add(menu12);
panel2.getMenus().add(menu13);
panel2.getMenus().add(menu14);
panel2.getMenus().add(menu15);
panel2.getMenus().add(menu16);
panel2.getMenus().add(menu17);
panel2.getMenus().add(menu18);
panel2.getMenus().add(menu19);

menuPanels=new ArrayList<MenuPanel>();
menuPanels.add(panel1);
menuPanels.add(panel2);

return menuPanelDao.add(menuPanels);
}


执行一下单元测试,看一下效果

@Test
public void test()
{
//		menuPanelService.delete();
menuPanelService.testAdd();
}

Hibernate: insert into MENUPANEL (text, id) values (?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENUPANEL (text, id) values (?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into MENU (leaf, parentId, menuPanelId, text, url, id) values (?, ?, ?, ?, ?, ?)

大家可以看到数据全部保存到数据库中了,有图有真像。

图一:MenuPanel表



[align=left] [/align]

图二:Menu表



[align=left] [/align]

再来看一下级联删除,级联删除可以用CascadeType.REMOVE,先在Menu中的getMenuPanel()方法中加上如下配置,由于我们已经在MenuPanel中配置了cascade=CascadeType.ALL,所以,下面的配置是可以忽略的,之所以这么做,是为了当从Menu中删除对象时能级联删除MenuPanel。
@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE}, targetEntity=MenuPanel.class)

在getMenu()方法中也加上如下配置
@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE}, targetEntity=Menu.class)


同在要把对象之间的关系解除
menus.get(j).setMenuPanel(null);


具体的代码

@Override
public boolean delete() {
// TODO Auto-generated method stub
Session session = null;
try {
session =getSession();
Query query = session.createQuery("from MenuPanel");
List<MenuPanel> list = query.list();
for (int i = 0; i < list.size(); i++) {
MenuPanel mp = list.get(i);
List<Menu> menus = mp.getMenus();

for (int j = 0; j < menus.size(); j++) {
menus.get(j).setMenuPanel(null);
clareChild(menus.get(j).getChildren());
}
super.delete(mp);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
//			session.close();
}
}


执行结果
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENUPANEL where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENU where id=?
Hibernate: delete from MENUPANEL where id=?


POJO类的详细代码如下:
package com.mcs.user.pojo;

import java.util.ArrayList;
import java.util.List;

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

import com.mcs.pojo.base.GenericObject;

/**
* 这个是MenuPanel对应的是accordion菜单
* @author lishengbo
*
*/
@Entity
@Table(name = "MENUPANEL")
public class MenuPanel extends GenericObject {
private String text;
private List<Menu> menus=new ArrayList<Menu>();

public MenuPanel() {
}

public MenuPanel(String text) {
this.text = text;
}
public MenuPanel(long id,String text) {
this.text = text;
super.setId(id+"");
}

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

/**
* 一对多关联Menu菜单,作为Tree中的根节点,这里使用立即加载和MenuPanel一起加载到客户端,注意,一定要使用立即加载
* @return
*/
@OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER,mappedBy="menuPanel")
public List<Menu> getMenus() {
return menus;
}

public void setMenus(List<Menu> menus) {
this.menus = menus;
}

}

package com.mcs.user.pojo;

import java.util.List;

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

import com.mcs.pojo.base.GenericObject;

@Entity
@Table(name="MENU")
public class Menu extends GenericObject{
private String text;
private String url;
private boolean leaf=true;//默认是叶子节点
private MenuPanel menuPanel;
private List<Menu> children;
private Menu menu;

public Menu() {
}

public Menu(String text, String url) {
super();
this.text = text;
this.url = url;
}
public Menu(long id,String text, String url,MenuPanel menuPanel) {
super();
super.setId(id+"");
this.text = text;
this.url = url;
this.menuPanel=menuPanel;
}
public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE}, targetEntity=MenuPanel.class)
@JoinColumn(name="menuPanelId",referencedColumnName="id",insertable=true,updatable=true)
public MenuPanel getMenuPanel() {
return menuPanel;
}

public void setMenuPanel(MenuPanel menuPanel) {
this.menuPanel = menuPanel;
}

@Column(length=1000)
public boolean isLeaf() {
return leaf;
}

public void setLeaf(boolean leaf) {
this.leaf = leaf;
}

@OneToMany(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY,mappedBy="menu") public List<Menu> getChildren() { return children; }
public void setChildren(List<Menu> children) {
this.children = children;
}

@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE}, targetEntity=Menu.class)
@JoinColumn(name="parentId",referencedColumnName="id",insertable=true,updatable=true)
public Menu getMenu() {
return menu;
}

public void setMenu(Menu menu) {
this.menu = menu;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: