hibernate关联关系

本文详细介绍了Hibernate中的一对多关联配置,包括配置文件的设置和实体类的设计,展示了如何在查询时获取关联数据。同时,讨论了懒加载的概念,指出默认情况下关联数据不会自动加载,需要通过特定方法强制加载。此外,还简述了一对多的自关联以及多对多关系的映射,强调在多对多关系中,中间表的数据维护只需由一方完成。
摘要由CSDN通过智能技术生成

数据库逻辑关系一共三种:

1.一对一

2.一对多

3.多对多

 在hibernate中,对数据库关系的操作也是按这三种关系展开,主要是考虑数据读取和维护。

  不过今天的目标不在这。

目标:

1,一对多的关联配置(数据库:主表从表,通过外键关联)将数据库中表与表之间的关系给映射到实体类里面

2,懒加载

3,一对多的自关联

4,多对多的关联,数据库中不能直接映射多对多(创建一个桥接表(中间表),将一个多对多关系转换成两个一对多)                                                                                    

 一、一对多的关联配置

上一次讲了将数据库中的单个表配置到hibernate中,需要建立实体类,和相关的配置文件,而直接被框架读取,与数据库进行交互的是配置文件。所以,数据库中表的关系描述也在配置文件中。

1.目标效果

如果是一般的不用关联的表,那就只会查出该表的数据,而配置过关联关系的,则可以查出相关联的表的对应数据

举例Order表——OrderItem表

order表字段

 

orderitem表字段

 实体类设计不放了。

实际需求:

在查询order数据时,希望把对应的orderitem数据也查出来。

很显然,只做最简单的表映射,是做不到这点的。所以需要在order和orderitem映射文件中加入关系映射代码。

order映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.csf.two.entity.Order" table="t_hibernate_order">
	<id name="orderId" type="java.lang.Integer" column="order_id">
		<generator class="increment"></generator>
	</id>
	
	<property name="orderNo" type="java.lang.String" column="order_no"/>
	
	<!-- 
		cascade:级联属性配置
		inverse:关联关系交给对方维护吗?
	 -->
	<set name="orderItems" cascade="save-update" inverse="true">
		<key column="oid"></key>
		<one-to-many class="com.csf.two.entity.OrderItem"/>
	</set>
</class>
</hibernate-mapping>

文中的set标签,便是映射关系。如果是

orderitem映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.csf.two.entity.OrderItem" table="t_hibernate_order_item">
	<id name="orderItemId" type="java.lang.Integer" column="order_item_id">
		<generator class="increment"></generator>
	</id>
	
	<property name="productId" type="java.lang.Integer" column="product_id"/>
	<property name="quantity" type="java.lang.Integer" column="quantity"/>
	<property name="oid" type="java.lang.Integer" column="oid"/>
	
	<!-- Repeated column in mapping for entity: com.zking.four.entity.OrderItem column: oid (should be mapped with insert="false" update="false") -->
	<many-to-one name="order" class="com.csf.two.entity.Order" insert="false" update="false" column="oid"></many-to-one>
	
</class>
</hibernate-mapping>

many-to-one标签,就是关系映射。

现在执行查询,

执行的就是选中的方法 

其实打印了两条sql语句,一条是根据id为7,查询order,另一条是根据查出来的order查询orderitem

最后也通过order拿到了相关的订单项。

注:图中的“order.serInitOrderItems(1)”,是定义在实体类中的开启强制加载,这就涉及到了hibernate的懒加载问题。

二、懒加载

在hibernate中,如果有关联关系的表映射出现,默认查询是懒加载,也就是不会查出连带数据,而需要查出连带数据的话,需要强制加载,而强制加载的弊端就是会占用空间,会影响运行速度,所以这里采用在实体类中用一个变量控制。具体查询方法如下。

        //并且想要查询出关联的订单项的数据是,采用强制加载
		if(o != null && new Integer(1).equals(order.getInitOrderItems())) {
		//强制加载订单o关联的订单项数据
			Hibernate.initialize(o.getOrderItems());
		}

如果不启用强制加载,会报错

could not initialize proxy - no Session

 三、一对多的自关联

例如在读取菜单的时候,节点字段是和上下节点相关联的。

因为结果和上面的差异都不大,就只放映射文件和实体类中关于关联关系的代码部分。

实体类中:

    private TreeNode parent;
	private Set<TreeNode> children = new HashSet<TreeNode>();
	private Integer initChildren = 0;

配置文件:

        <many-to-one name="parent" class="com.csf.two.entity.TreeNode" column="parent_node_id"/>
		
		<set name="children" cascade="save-update" inverse="true">
			<key column="parent_node_id"></key>
			<one-to-many class="com.csf.two.entity.TreeNode"/>
		</set>

也就是将一对多和多对一全写在这里

四、多对多

例如在老师与班级的关系中,一个老师可能对应着多个班级,而班级会对应这不同的多个任课老师,而一般老师与班级只会建立两张表储存数据,而还会再建立一张中间表,以描述关系,这就构成了多对多的关联关系。

而多对多,以任何一方做参照看来,都是一对一,所以可以将一个多对多关系理解为两个一对多关系,而在hibernate中,也就是双方都有一对多的关联关系。而这里的一对多关系,是和中间表的关系。(中间表不建立实体类)

代码(以Book和Category为例)

实体类

Book

private Set<Category> categories = new HashSet<Category>();

book.hbm.xml

<!--
		table :中间表
		name:g关联属性
		inverse:反转
		key:当前表的主键在中间表的外键
		many-to-many:当前表的主键在中间表查出另一表的外键
		  -->
		
		<set table="t_hibernate_book_category" name="categories" cascade="save-update" inverse="false">
			<!-- one -->
			<key column="bid"></key>
			<!-- many -->
			<many-to-many column="cid" class="com.csf.two.entity.Category"></many-to-many>
		</set>

Category

private Set<Book> books = new HashSet<Book>();
        <set table="t_hibernate_book_category" name="books" cascade="save-update" inverse="true">
			<key column="cid"></key>
			<many-to-many column="bid" class="com.csf.two.entity.Book"></many-to-many>
		</set>

ok,

注:在多对多的关联关系中,中间表的数据维护只需要让其中一方做就可以,不能两个同时维护或都不维护。也就是inverse属性,(为true代表维护,反之则代表不维护)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无感_K

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

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

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

打赏作者

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

抵扣说明:

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

余额充值