Hibernate总结--一对多

数据表中种存在一对一、一对多、多对一的关系,比如部门表跟员工表就存在一对多的关系,一个部门对应多个员工,Hibernate中使用one-to-many、many-to-one、one-to-one来处理这些关系

一、SQL语句

    订单表

CREATE TABLE `order` (
  `ORDER_ID` int(2) NOT NULL AUTO_INCREMENT,
  `ORDER_NAME` varchar(30) DEFAULT NULL,
  `CUSTOMER_ID` int(2) DEFAULT NULL,
  PRIMARY KEY (`ORDER_ID`),
  KEY `customer_id_fk` (`CUSTOMER_ID`),
  CONSTRAINT `customer_id_fk` FOREIGN KEY (`CUSTOMER_ID`) REFERENCES `customer` (`CUSTOMER_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

  顾客表

CREATE TABLE `customer` (
  `CUSTOMER_ID` int(2) NOT NULL,
  `CUSTOMER_NAME` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`CUSTOMER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

顾客和订单是一对多关系,一个顾客对应多个订单

二、实体和表映射文件

  顾客实体(省略getter和setter)

public class Customer implements java.io.Serializable {

	// Fields

	private Integer customerId;
	private String customerName;
	
	/*
	 * 1.声明集合类型时, 需使用接口类型, 因为 hibernate 在获取
	 * 集合类型时, 返回的是 Hibernate 内置的集合类型, 而不是 JavaSE 一个标准的
	 * 2.需要把集合初始化化,否则会出现空指针异常
	 */
   private Set<Order> orders = new HashSet<>();
}

注:一那一方的实体需要一个set来装载多的一方

顾客表映射文件

<?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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.zhuojing.hibernate.entities.onetomany.Customer" table="customer" catalog="hibernate">
        <id name="customerId" type="java.lang.Integer">
            <column name="CUSTOMER_ID" />
            <generator class="assigned" />
        </id>
        <property name="customerName" type="java.lang.String">
            <column name="CUSTOMER_NAME" length="30" />
        </property>
        
        <!-- 映射1 对 多 -->
        <!-- set:映射 set 类型属性,table:set 中元素对应的记录放在哪一个数据表中,该值需要和多对一的多的那个表的名字一致 -->
        <!-- inverse:指定由哪一方来维护列的名字 ,通常设置为true,以指定由对方来维护关联关系,这边在set设置true就表示交给1的一方维护,set代表多的一方-->
        <!-- cascade:设定级联操作,开发时候不建议设定这个属性,建议用手工的操作 -->
        <!-- order-by:在查询时对集合的元素进行排序,order-by 中使用是表的字段名,不是持久化的属性名 -->
        <set name="orders" inverse="true" table="order" cascade="delete" order-by="ORDER_NAME ASC">
            <!-- 指定多的表中的外键的列的名字 -->
            <key>
                <column name="CUSTOMER_ID" />
            </key>
            <!-- 指定映射关系 -->
            <one-to-many class="com.zhuojing.hibernate.entities.onetomany.Order"/>
        </set>
        
    </class>
</hibernate-mapping>

订单实体

public class Order implements java.io.Serializable {

	// Fields

	private Integer orderId;
	private Customer customer;
	private String orderName;
}

订单表映射文件

<?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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.zhuojing.hibernate.entities.onetomany.Order" table="order" catalog="hibernate">
        <id name="orderId" type="java.lang.Integer">
            <column name="ORDER_ID" />
            <generator class="identity" />
        </id>
        <property name="orderName" type="java.lang.String">
            <column name="ORDER_NAME" length="30" />
        </property>
        <!-- 
                                             映射多对一的关联关系:使用 many-to-one 来映射多对一关联关系 
             name:多对一关联的属性的名字
             class:一的那一端的属性对应的类名
             column:一那端在多的一端对应的数据表的外键的名字
        -->
        <many-to-one name="customer" class="com.zhuojing.hibernate.entities.onetomany.Customer" fetch="select">
            <column name="CUSTOMER_ID" />
        </many-to-one>
    </class>
</hibernate-mapping>

四、测试类

package com.zhuojing.hibernate.entities.onetomany;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

import javax.imageio.stream.FileImageInputStream;

import org.hibernate.Hibernate;
import org.hibernate.LazyInitializationException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class HibernateOneToManyTest {

	
	private SessionFactory sessionFactory;
	
	private Session session;
	
	private Transaction transaction;
	
	@Before
	public void init() {
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = 
				new ServiceRegistryBuilder().applySettings(configuration.getProperties())
				                            .buildServiceRegistry();
		
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		
		transaction = session.beginTransaction();
	}
	
	@After
	public void destroy(){
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	@Test
	public void testOneToManySave(){
		Customer customer = new Customer(10, "DD");
		Order order1 = new Order(customer, "ORDER-7");
		
		Order order2 = new Order(customer, "ORDER-8");
		
		customer.getOrders().add(order1);
		customer.getOrders().add(order2);
		
		//先插入一的一端,再插入多的一端:只有三条INSERT,两天 UPDATE 语句
		//可以在1 的一端set 节点指定inverse=true,来使1 的一端放弃,维护关系,来减少 2 条UPDATE
		session.save(customer);
		session.save(order1);
		session.save(order2);
		
		//先查诶多的一端,再插入一的一端:3条INSERT,4条UPDATE
		//因为在插入多的一端是,无法确定1的一端的外键值,所有智能等1的一端插入后,再额外发送UPDATE 语句
		//推荐先插入一端,在插入多一端
		/*session.save(order1);
		session.save(order2);
		session.save(customer);*/
	}
	
	@Test
	public void testOneToManyQuery(){
		
		//1.对n 的一端的集合使用延迟加载
		Customer customer = (Customer)session.get(Customer.class, 6);
		System.out.println(customer.getCustomerName());
		//2.返回的n 的一端的集合是 Hibernate 内置的集合类型,该类型具有延迟加载和存放代理类的功能
		System.out.println(customer.getOrders().getClass());
		System.out.println(customer.getOrders().toString());
		//可能会抛出 LazyInitializationException异常
		
		//4.在需要使用集合元素的时候进行初始化
	}
	
	
	@Test
	public void testOneToManyUpdate(){
		Customer customer = (Customer)session.get(Customer.class, 5);
		customer.getOrders().iterator().next().setOrderName("ABCD");
			
	}
	
	@Test
	public void testManyToOneDelete(){
		
		//在不设定定级联关系的情况下,且1这个一端的对象有 n 的对象在引用,不能直接删除 1 这一端的对象
		Customer customer = (Customer)session.get(Customer.class, 5);
		
		session.delete(customer);
	}
	
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值