Hibernate----------配置文件详解(二)

前言:


上一篇文章我们学习了Hibernate的配置详解,主要包括两个配置文件,

hibernate.cfg.xml和hbm.xml。

今天继续来学习hbm.xml中两个重要的配置:

inverse和cascade。


1.inverse

在具体业务场景中,Customer和Orders是一对多关系,一个Customer对应多个Orders,实体类中用一个set集合作为属性来表示对应的Orders。


public class Customer implements Serializable {
	private Integer id;
	private String name;
	private Set orders;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set getOrders() {
		return orders;
	}
	public void setOrders(Set orders) {
		this.orders = orders;
	}
	
}

Customer.hbm.xml文件中用set标签来配置映射关系。






	
		
		
			
			
		
		
		
		
		
		
			
			
			
		
	

同理在Orders实体类中用一个Customer类型的属性来表示对应的Customer对象。


public class Orders implements Serializable {
	private Integer id;
	private String name;
	private Customer customer;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
	
}

Orders.hbm.xml中,用many-to-one标签来配置映射关系。






	
		
		
			
			
		
		
		
		
		
		
		
	

从配置文件中可以看出,Customer和Orders是双向维护关系,即Customer在维护一对多关系,同时Orders也在维护一对多关系,在实际开发代码过程中,就可能会出现重复维护的情况。


创建一个Customer对象,创建两个Orders对象,并建立关联关系,Orders对象来维护一对多关系,代码如下。


//4.创建Session对象
        Session session = sessionFactory.openSession();

        //5.创建Customer对象
        Customer customer = new Customer();
        customer.setName("张三");

        //6.创建Orders对象
        Orders orders = new Orders();
        orders.setName("订单1");
        Orders orders2 = new Orders();
        orders2.setName("订单2");

        //7.建立关联关系
        orders.setCustomer(customer);
        orders2.setCustomer(customer);

        //8.保存
        session.save(customer);
        session.save(orders);
        session.save(orders2);

        //9.提交事务
        session.beginTransaction().commit();

        //10.关闭session
        session.close();

执行代码,打印3条SQL语句,向customer表添加1条记录,向orders表添加2条记录,并且将customer的id值赋给oid字段,建立主外键约束关系。这段代码没有什么问题。


Hibernate----------配置文件详解(二)_第1张图片


此时修改Java代码,让Customer对象也来维护一对多关系。


//创建customer对象
        Customer customer = new Customer();
        customer.setName("李四");

        //创建orders1对象
        Orders orders1 = new Orders();
        orders1.setName("订单3");
        //将customer赋给orders1
        orders1.setCustomer(customer);

        //创建orders2对象
        Orders orders2 = new Orders();
        orders2.setName("订单4");
        //将customer赋给orders2
        orders2.setCustomer(customer);

        //创建集合,将orders1,orders2加入集合
        Set ordersSet = new HashSet();
        ordersSet.add(orders1);
        ordersSet.add(orders2);
        //将Orders集合赋给customer
        customer.setOrders(ordersSet);

        //保存
        session.save(customer);
        session.save(orders1);
        session.save(orders2);

        //提交事务
        session.beginTransaction().commit();
        
        //关闭session
        session.close();

再次执行代码,打印5条SQL,向customer表添加1条记录,向orders表添加2条记录,并且将customer的id值赋给oid字段,建立主外键约束关系。

同时多了2条修改操作,再一次将customer的id值赋给oid字段,这2条SQL语句是在重复设置已经建立的主外键约束关系。

Hibernate----------配置文件详解(二)_第2张图片

为什么会出现这种情况?


因为当前Customer和Orders对象都在维护关系,所以会重复建立两次主外键约束。


如何避免这种情况的出现呢?


第一种方式:在Java代码中去掉一方维护关系的代码。


第二种方式:通过设置hbm.xml文件来完成。


通常我们让多的一方来维护关系,即让Orders来维护,所以就需要让Customer放弃维护,在Customer.hbm.xml中设置set标签的inverse属性。


inverse属性是用来设置是否将维护权交给对方,默认为false,即不交出维护权,双方都在维护关系。


现在将invers设置为true,表示当前Customer已经放弃了维护权。



    
    
    

再次运行代码。


Hibernate----------配置文件详解(二)_第3张图片


看到控制台打印3条SQL,即建立了一次主外键约束关系,并且是由Orders来维护的。


2.cascade:用来设置级联操作。


我们知道在删除一条主表数据时,一定要先清除被它约束的从表记录,

即在删除Customer对象时,必须先删除该对象对应的Orders对象,否则直接报错。


Hibernate----------配置文件详解(二)_第4张图片

Hibernate----------配置文件详解(二)_第5张图片


错误原因是因为被删除记录的主键正在约束orders表中的外键,必须先解除约束关系,才可删除。


如何解决?


第一种方式:修改Java代码,迭代Customer对象包含的所有Orders对象,将这些Orders对象全部删除,再删除Customer对象。

Customer customer = (Customer) session.get(Customer.class, 2);
        //迭代orders集合
        Iterator iter = customer.getOrders().iterator();
        while(iter.hasNext()){
            Orders orders = (Orders) iter.next();
            //删除orders对象
            session.delete(orders);
        }
        session.delete(customer);
        session.beginTransaction().commit();
        session.close();   

第二种方式:不需要修改Java代码,在hbm.xml中设置级联删除属性即可,设置cascade="delete"。


cascad:有4个值可以选择。

1.all : 所有情况下均进行关联操作。

2.none:所有情况下均不进行关联操作。这是默认值。

3.save-update在执行save/update/saveOrUpdate时进行关联操作。

4.delete:在执行delete时进行关联操作。



    
    
    

执行代码。


Hibernate----------配置文件详解(二)_第6张图片


会看到控制台会打印3条delete语句,前2条是删除Customer对象关联的2个Orders对象,第3条是删除Customer对象本身。


采用这种方式,我们不需要在逻辑代码中手动删除级联对象,Hibernate框架会自动帮我们删除这些对象。


你可能感兴趣的:(hibernate,Hibernate)