欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Hibernate关联关系

程序员文章站 2022-04-22 22:57:28
...

Hibernate关联就是将关联映射到数据库,所谓关联关系就是对象模型在内存中的一个或多个引用。

先看两个关系实体类: 都提供set/get方法

public class Order {
	private Integer orderId;
	private String orderNo;
	private List<OrderItem> orderItems = new ArrayList<>();
	private Integer initChildren =0;  //0代表懒加载  默认为0
	
}
public class OrderItem {
	private Integer orderItemId;
	private Integer productId;
	private Integer quantity;
	private Integer oid;
	private Order order;
}

下面介绍几种单向的关联关系。

一、单向N-1

所谓的单向1-N,也就是一个a实体类中有可以有多个b实体类的关系。
xml配置:

<many-to-one name="orderItem" column="productId"/>

二、单向的1-1

这种情况也是使用many-to-one,
不过在标签中多加一个unique=true这个属性,
这个属性代表的是限制了多的一端的多重性唯一。
通过这种手段可以映射一对一唯一外键关联。
xml配置:

<many-to-one name="address" column="oid" unique="true"/>

三、单向的1-N

一对多关联映射,在多的一端添加一个外键指向一的一端,它维护的关系是一指向多。
xml配置:

<!-- 
	bag标签:
		 lazy:是否懒加载,默认是懒加载
		 name:类的关联属性名
		 cascade:级联关系  级联新增与修改
		 inverse:关联关系交给对方控制,默认是true  意思就是当前类不维护关联关系
		 
		 子标签key:
		 	column:主表的主键,从表的外键。一般写从表的外键
		 子标签one-to-many:
		 	class:外键对应的实体类
		 
 -->
	<bag lazy="true" name="orderItems" cascade="save-update" inverse="true">
		<key column="oid"></key>
		<one-to-many class="com.zlk.three.entity.OrderItem"/>
	</bag>

在这里有两个选择,可以选择bag标签也可以使用set标签,
bag是一个无序的集合,它可以包含重复的元素,相当于java的java.util.List。
set类似于bag,但它只能存储唯一对象,若元素相同,则新的会替换掉旧的元素。类似Java中的java.util.Set。

四、单向N-N

两个实体类:

public class User {
	private int id;
	private String name;
	private Set roles;
}
public class Role {
private int id;
private String name;
}

现在需要映射这样的N-N关系,一个User可以有多个Role,而一个Role有可以被多个User所拥有。
这样我们就可以将一个N-N关系拆分为两个N-1的关系。
xml配置:

<bag name="roles" table="t_user_role">
<key column="userid"/>
<many-to-many class="xxx.Role" column="roleid"/>
</bag>

参考在这,想了解更多关系,请参考如何理解hibernate关联关系

懒加载

四种模式已经介绍完了,在这里我先着重讲解一下1-N。
在1-N的xml配置中:

<bag lazy="true" name="orderItems" cascade="save-update" inverse="true">
			<key column="oid"></key>
			<one-to-many class="com.zlk.three.entity.OrderItem"/>
		</bag>

上面介绍过lazy是懒模式。他默认是true,那什么是懒模式呢?
当lazy= false 的时候,会让hibernate执行完两次操作,session才会关闭,
当lazy= true 的时候,会让hibernate执行完一次操作,session就会关闭
为什么要默认true呢?
出于性能的考虑,所以hibarnate3.0出现lazy这个属性,并让他默认等于true,也就是不加载关联属性。
可以使用JUnit测试一下,

	@Test
	public void testGetOrder() {
		Order order = new Order();
		order.setOrderId(1);
		Order o = this.demoDao.getOrder(order );
		List<OrderItem> orderItems = o.getOrderItems();
		for (OrderItem orderItem : orderItems) {
			System.out.println(orderItem);
		}
		System.out.println(o);
	}

当lazy=false时候,他会正常运行,并打印出数据。
当lazy=true时候,他会报no-Session错,这是因为允许了懒加载,只执行了一次操作,所以 List orderItems = o.getOrderItems();这里面是没有值的,
但如果我只是单纯的写要查出所有的订单那怎么办呢?
这里就运用到了上面实体类中的private Integer initChildren =0; //0代表懒加载 默认为0。
通过这个属性来控制是否强制加载关联对象。

		public Order getOrder(Order order) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Order o = session.get(Order.class, order.getOrderId());
		if(o != null && new Integer(1).equals(order.getInitChildren())) {
			//强制加载关联对象
			Hibernate.initialize(o.getOrderItems());
		}
		transaction.commit();
		session.close();
		return o;
	}

这样就可以使用懒加载查看所有订单了。

删除对应数据

若你想删除订单的时候,这时候不能直接删除订单,因为你的从表OrderItem里面还是有数据的,所以你必须先删除从表里面的值,才可以删除order。
方法如下:

	public void delOrder(Order order) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Order order2 = session.get(Order.class, order.getOrderId());
		for (OrderItem oi : order2.getOrderItems()) {
			session.delete(oi);
		}
		session.delete(order2);
		transaction.commit();
		session.close();
	}

hibernate框架一对多的执行原理

hibernate框架一对多的执行原理:
1,对hibernate.cfg.xml进行建模,等到sessionfactory对象
2,并且拿到mapping resourse里的内容
3,拿到order.hbm.xml配置文件
4,可以再次建模,拿到实体类属性和对应的数据库表列段
5,生成动态的sql:select * 表名
执行sql最终得到meterData原数据模型
6,通过实体类进行反射 Class.forName(“com.zlk.three.entity.Order”).newInstance(0);
获得所有数据库内的数据。
最终得到List,且里面都有值(到这里只是处理了表里面的非外键列段)
7,处理关联关系 :通过标签获得orderItems(所有订单) oid 和订单实体类com.zlk.three.entity.OrderItem
然后通过one-to-many 里的 class(也就是com.zlk.three.entity.OrderItem),就可获得这个实体类的xml,
再通过这个xml获得对应的数据库表。
8,与第五步相同,最终获得了一个list
9,给order的关联关系属性赋值
就是在第六步中获得List时,一个一个的加进去:
for(Order o:List){
o.setOrderItems(List );
}

相关标签: Hibernate关联关系