hibernate多对一关联和一对多关联

版权声明: https://blog.csdn.net/zdp072/article/details/51146349

1. 多对一的单向关联

从订单(order)到客户(customer)的单向关联 (多个订单对应一个客户)

JavaBean: Customer

public class Customer{
	private Integer id;
	private String name;
}
JavaBean: Order
public class Order{
	private Integer id;
	private String orderNumber;
	private Double price;
	private Customer customer;   // 建立从订单到客户的多对一关联
}
customer.hbm.xml:
<hibernate-mapping>
<class name="cn.itcast.many2one.Customer" table="customers">
	<id name="id" type="integer">
		<column name="id"></column>
		<generator class="increment"></generator>
	</id>
	<property name="name" type="string" access="property">
		<column name="name"></column>
	</property>
</class>
</hibernate-mapping>
order.hbm.xml:
<hibernate-mapping>
	<!-- class标签建立javabean和表之间的映射 -->
	<class name="cn.itcast.many2one.Order" table="orders">
		<!-- id映射表中的主键 -->
		<id name="id" type="integer">
			<column name="id"></column>
			<!-- 配置主键的生成策略 -->
			<generator class="increment"></generator>
		</id>
		<!-- 
			property建立javabean中的属性和表中列的对应关系
			type="string": string表示的是hibernate的类型,该类型是java类型和sql类型之间的桥梁
			java中的类型: String name; sql中的类型: varchar(255);
			映射一个sql的varchar类型到java的String类型
		 -->
		<!-- access属性表示对javabean属性的访问策略,默认值是property  -->
		<property name="orderNumber" type="string" access="property">
			<!-- column定义表中的列    -->
			<column name="orderNumber"></column>
		</property>
		<property name="price" type="double">
			<column name="price"></column>
		</property>
		<!—
			  <many-to-one>: 使用该标签来映射多对一关联
			* name: 映射的持久化类中的属性
            * class: 映射的持久化类中的属性的类型
              cascade="save-update"   级联保存和更新
            * 就是将order对象所关联的临时对象Customer变成持久对象
              持久对象会保存在session的一级缓存中,就能插入到数据库中
              update=”false” 指的是不能用session.update(),session.saveOrUpdate()的方式更新
              但是可以用hql语句进行更新
		-->
		<many-to-one name="customer" class="cn.itcast.many2one.Customer" cascade=”save-update”>
			<column name="customer_id" ></column>     <!-- column表示多的一方(Role)表中的外键 -->
		</many-to-one>
	</class>
</hibernate-mapping>
2. 一对多的单向关联
从客户(customer)到订单(order)的单向关联 (一个客户对应多个订单)

JavaBean: Customer

public class Customer{
	private Integer id;
	private String name;
	private Set<Order> orders = new HashSet<Order>(0);  // 开始长度为0
}

JavaBean: Order

public class Order{
	private Integer id;
	private String orderNumber;
	private Double price;
}
Customer.hbm.xml:
<hibernate-mapping>
<class name="cn.itcast.many2one.Customer" table="customers">
	<id name="id" type="integer">
		<column name="id"></column>
		<generator class="increment"></generator>
	</id>
	<property name="name" type="string" access="property">
		<column name="name"></column>
	</property>
	<!--
		配置set集合
		Set: 使用set标签配置客户对应的订单集合
		table:订单集合中的订单对应的表,可以不加
		cascade=”save-update”: 级联保存和更新,当保存customer对象时,同时要保存customer对象多关联的订单集合orders集合
        “delete”: 级联删除,删除客户的同时删除订单
		inverse=”true”: 表示多的一端(order端) 为主控方法      ---> 看成”全国人民”  全国人民可以记住国家主席 (多的一端说了算)
        一的一端(customer端) 不是主控方法   ---> 看成”国家主席”  国家主席是记不住全国人的
        Update的时候才有效!!! 如果不写默认的是两边都维护
	-->
	<set name=”orders” table=”orders” inverse=”true”>
		<key>
			<!--对应是orders表的外键,可以理解为orderes集合中的订单对象是通过orders表的外键customer_id查询出来的-->
			<column name=”customer_id”/>
		</key>
		<!--  one-to-many表示一对多, class表示集合中存放的对象是Order对象 -->
		<one-to-many class=” cn.itcast.many2one.Order”/>
	</set>
</class>
</hibernate-mapping>
Order.hbm.xml:

<hibernate-mapping>
	<class name="cn.itcast.many2one.Order" table="orders">
		<id name="id" type="integer">
			<column name="id"></column>
			<generator class="increment"></generator>
		</id>
		<property name="orderNumber" type="string" access="property">
			<column name="orderNumber"></column>
		</property>
		<property name="price" type="double">
			<column name="price"></column>
		</property>
	</class>
</hibernate-mapping>
3. 一对多的双向关联
建立从Customer到Order的一对多的双向关联

* 从一的一端查询关联到多的一端

* 从多的一端查询关联到一的一端

* 双向一对多和双向多对一是两种完全相同的情形

JavaBean: Customer

public class Customer{
	private Integer id;
	private String name;
	private Set<Order> orders = new HashSet<Order>(0);  // 开始长度为0
}
JavaBean: Order
public class Order{
	private Integer id;
	private String orderNumber;
	private Double price;
	private Customer customer;   // 建立从订单到客户的多对一关联
}
Customer.hbm.xml:
<hibernate-mapping>
	<class name="cn.itcast.many2one.Customer" table="customers">
		<id name="id" type="integer">
			<column name="id"></column>
			<generator class="increment"></generator>
		</id>
		<property name="name" type="string" access="property">
			<column name="name"></column>
		</property>
		<!--
			配置set集合
			name: Customer类的orders属性
			table: 对应表的表名
			set: 使用set标签配置客户对应的订单集合
			table:订单集合中的订单对应的表,可以不加
			cascade=”save-update”: 级联保存和更新,当保存customer对象是,同时要保存customer对象所关联的订单集合Orders集合
			不要设置成cascade=”all”,因为删除一条,其他被关联的也会被删除掉
			inverse:是否放弃维护表关系
			lazy:是否是懒加载,如果设置为false,则即使不使用它的子元素也会执行查询,影响效率。
		-->
		<set name=”orders” table=”orders” cascade=”save-update”>
			<key>
				<!—对应是orders表的外键,可以理解为orderes集合中的订单对象是通过orders表的外键customer_id查询出来的-->
				<column name=”customer_id”/>
			</key>
			<!--  one-to-many表示一对多, class表示集合中存放的对象是Order对象 -->
			<one-to-many class=” cn.itcast.many2one.Order”/>
		</set>
	</class>
</hibernate-mapping>
Order.hbm.xml:
<hibernate-mapping>
	<class name="cn.itcast.many2one.Order" table="orders">
		<id name="id" type="integer">
			<column name="id"></column>
			<generator class="increment"></generator>
		</id>
		<property name="orderNumber" type="string" access="property">
			<column name="orderNumber"></column>
		</property>
		<property name="price" type="double">
			<column name="price"></column>
		</property>
		<!—
			<many-to-one>: 使用该标签来映射多对一关联
			* name: 映射的持久化类中的属性
			* class: 映射的持久化类中的属性的类型
			cascade="save-update"   级联保存和更新
			* 就是将order对象所关联的临时对象Customer变成持久对象
			  持久对象会保存在session的一级缓存中,就能插入到数据库中
		-->
		<many-to-one name="customer" class="cn.itcast.many2one.Customer" cascade=”save-update”>
			<column name="customer_id" ></column>
		</many-to-one>
	</class>
</hibernate-mapping>
public void testDoubleRaletion(){
	Session session = sf.openSession();
	Transaction tx = session.beginTransaction();

    Order orders1=new Order();
	orders1.setOrderNumber("001");
	orders1.setPrice(20);

	Customer c=new Customer();
	c.setName("杨逍");
		
	//建立订单和客户的双向关联
	//订单和客户关联
	orders1.setCustomer(c);

	//客户和订单关联
	//c.getOrders().add(orders1);

	session.save(c);
	session.save(orders1);
	tx.commit();
	session.close();
}
4. 1个javabean映射2张表

一个人在网上有多张相片

对于子表中除了外键,只有一列数据, 可以建立一个JavaBean映射两个表

表的数量一般情况下和javabean的数量保持一致,但这不是绝对的,就比如我们这个例子

建表语句:

CREATE table persons(
    pid INT,
    name varchar(20)
);
CREATE table imgs(
    imgid INT,
    img varchar(20)
);
alter table persons 
add CONSTRAINT persons_pk primary key (pid);
alter table imgs 
add constraint imgs_fk foreign key imgs(imgid) references persons(pid);
JavaBean:
public class Person {
	private Integer id;
	private String name;
	private Set<String> imgs = new HashSet<String>();    // 将另一个表映射成自己的一个集合
     ... get和set方法
}
Person.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.domain2">
	<class name="Person" table="persons">
		<id name="id" type="integer">
			<column name="pid"></column>
			<generator class="increment"></generator>
		</id>
		<property name="name" column="name" type="string"/>
		<!-- 以下通过一个Set元素映射Person类中的set集合
			 name是指:Person类中的成员变量名,用set映射,说明它是一个Set类型的对象
			 table:是指Person类中的成员变量imgs的数据来自于imgs表
		 -->
		<set name="imgs" table="imgs">
			<!-- 只要指定了另一个表,必须要指定另一个表中的外銉是哪一个字段 -->
			<key column="imgid"></key>
		    <!-- 因为另一个表中,即imgs表中,除了外键之外只有一个字段,所以可以使用element元素影射
		    	element的column属性是指items.imgs属性的值都来自于imgs表的img字段.
		     -->
		    <element column="imgname" type="string"></element>
		</set>
	</class>
</hibernate-mapping>

拓展: 查询没有图片的人
方法1:
select pid,pname,imgname       // 查询两张表
from persons p left join imgs i on p.pid=i.imgid
where i.imgname is null;

方法2:
SELECT * 
FROM persons 
<span style="font-family:Comic Sans MS;">WHERE NOT EXISTS (SELECT * FROM imgs WHERE persons.pid=imgs.imgid);
</span>
5. bag和set的区别
Set:   new HashSet()  - 无序, 不能重复。 
Bag:   new ArrayList()     用bag来映射的List是无序的集合, 可以重复

          new LinkedArrayList()

配置文件书写略有不同:
<set name="emps" table="emp" cascade="save-update" inverse="false" lazy="true">
			<key column="edept"></key>
			<one-to-many class="Emp"/>
</set>

<bag name="cars" cascade="save-update" inverse="false">
			<key column="c_pid"/>
			<one-to-many class="Car"/>
</bag>

展开阅读全文

没有更多推荐了,返回首页