Hibernate级联保存与删除

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

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

       从上图可以看出,MenuPanelMenu是一对多的关系,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;
	}


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

@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表

      

 

图二:Menu

 

 

         再来看一下级联删除,级联删除可以用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;
	}
	
	
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lishengbo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值