Video-No.02 尚硅谷_Hibernate4视频教程

1、Ecplise hibernate插件安装:

    下载zip格式的Eclipse插件,(http://sourceforge.net/projects/jboss/files/JBossTools/JBossTools4.1.x/hibernatetools-Update-4.1.1.Final_2013-12-08_01-06-33-B605.zip) 

    Eclipse-》Help-》Install New Software.. -》add..-》Archive 选择刚才下载的hibernate插件

2、Hibernate开发步骤

    1)创建hibernate配置文件(hibernate.cfg.xml):配置数据库相关配置信息和hibernate相关初始化配置信息

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
    
    	<!-- 数据库连接配置信息 -->
    	<property name="connection.username">root</property>
    	<property name="connection.password">root</property>
    	<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    	<property name="connection.url"><![CDATA[jdbc:mysql://127.0.0.1:3306/atguigu_hibernate?useUnicode=true&characterEncoding=utf8]]></property>
   
   	<!-- hibernate基本配置信息  -->
   		
   	<!-- hibernate数据库方言 -->
   	<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
   		
   	<!-- 执行操作时,是否在后台打印SQL语句 -->
   	<property name="show_sql">true</property>
   		
   	<!-- 是否对SQL语句进行格式化 -->
   	<property name="format_sql">true</property>
   		
   	<!-- 指定自动生成数据表的策略 -->
   	<!-- 
   		create: 会根据*.hbm,xml文件生成新的数据表,每次都会删除上一次的数据表重新生成表
   		create-drop:会根据*.hbm,xml文件生成新的数据表,但是每次sessionFactory关闭都会删除表
   		update:最常用的值,会根据*.hbm,xml文件生成新的数据表,如果*.hbm,xml所定义的表结构与数据库中表结果不同,hibernate将更新数据表结构,但不会删除已有的行和列
   		validate:会和数据库中的表进行比较,如果*.hbm,xml配置文件中的列在数据库中不存在,则抛出异常
   	-->
   	<property name="hbm2ddl.auto">update</property>
   		
   	<!-- 设置 Hibernate 的事务隔离级别 -->
   	<property name="connection.isolation">2</property>
   		
   	<!-- 删除对象后, 使其 OID 置为 null -->
   	<property name="use_identifier_rollback">true</property>
   		
       <!-- 配置 C3P0 数据源 -->
    	<property name="hibernate.c3p0.max_size">10</property>
    	<property name="hibernate.c3p0.min_size">5</property>
    	<property name="c3p0.acquire_increment">2</property>
    	
    	<property name="c3p0.idle_test_period">2000</property>
    	<property name="c3p0.timeout">2000</property>
    	
    	<property name="c3p0.max_statements">10</property>
    	
    	<!-- 设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数 -->
    	<property name="hibernate.jdbc.fetch_size">100</property>
    	
    	<!-- 设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小 -->
    	<property name="jdbc.batch_size">30</property>
   		
   	<!-- 指定关联的map映射 -->
   	<mapping resource="com/shma/hibernate/entity/User.hbm.xml"/>
   	<mapping resource="com/shma/hibernate/entity/Worker.hbm.xml"/>	
    </session-factory>
    
</hibernate-configuration>

    2)创建持久化层实体类

package com.shma.hibernate.entity;

import java.sql.Blob;
import java.util.Date;

public class User {

	private Integer id;
	private String name;
	private Integer age;
	private Date date;
	
	private String oldContent;
	private Blob image;
	
	private String desc;
	
	public User() {
		super();
	}
	
	public User(String name, Integer age, Date date) {
		super();
		this.name = name;
		this.age = age;
		this.date = date;
	}
	
	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 Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public String getOldContent() {
		return oldContent;
	}

	public void setOldContent(String oldContent) {
		this.oldContent = oldContent;
	}

	public Blob getImage() {
		return image;
	}

	public void setImage(Blob image) {
		this.image = image;
	}
}

package com.shma.hibernate.entity;

public class Worker {

	private int id;
	private String name;
	
	private Pay pay;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Pay getPay() {
		return pay;
	}

	public void setPay(Pay pay) {
		this.pay = pay;
	}
}

package com.shma.hibernate.entity;

public class Pay {

	private double monthPay;
	private double yearPay;
	private int yearDay;
	
	private Worker worker;
	
	public double getMonthPay() {
		return monthPay;
	}
	public void setMonthPay(double monthPay) {
		this.monthPay = monthPay;
	}
	public double getYearPay() {
		return yearPay;
	}
	public void setYearPay(double yearPay) {
		this.yearPay = yearPay;
	}
	public int getYearDay() {
		return yearDay;
	}
	public void setYearDay(int yearDay) {
		this.yearDay = yearDay;
	}
	public Worker getWorker() {
		return worker;
	}
	public void setWorker(Worker worker) {
		this.worker = worker;
	}
	
	
}

    3)创建对象-关系映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.shma.hibernate.entity">
	<!-- 
		class:
		1)dynamic-insert:默认为false,如果设置为true,则表示保存一个insert时,动态生成sql语句,仅保存字段不能为空的值
		2)dynamic-update:默认为false,如果设置为true,则表示更新一个update时,动态生成sql语句,仅更新修改的字段值
	 	3)select-before-update:在执行update之前,是否执行一次查询,默认为false
	 -->
    <class name="User" table="USER" select-before-update="true" dynamic-insert="true">
        <!-- 
      		id:
      		unsaved-value:表示持久化对象的oid如果为该属性值20,则认为是一个临时对象,执行保存操作
      		type:可以为java类型,也可以设置为hibernate类型
      		class:设置持久化类设置唯一标识符方式
      			increment:由hibernate先执行查询max,再+1,并发下不安全
      			identity:底层数据库自增,底层数据库必须设置为自增,适用于mysql、sqlserver
      			sequence:底层数据库提供序列生成唯一标识符,如oracle
      			hilo:hibernate生成组件,在数据库创建一张表,读取并修改该表保存自增
      			native:常用,自动识别使用identity、sequence、hilo
         -->
        <id name="id" type="java.lang.Integer" unsaved-value="20">
            <column name="ID"  />
            <generator class="native" />
        </id>
        <!-- 
        	property:
        		1) access:制定hibernate默认属性访问策略,默认为property,调用getter和setter方法,若设置为field,则通过反射访问
        		2) unique:设置属性唯一值
        		3) index:设置索引
        		4) length: 设置字段长度
        		5) scale: 当字段为double或float类型时,指定小数点后保留位数
        		6) formula: 派生属性,sql表达式,用()括起来
         -->
        <property name="name" type="java.lang.String" 
        		access="property" unique="true" index="user_index" length="20">
            <column name="NAME" />
        </property>
        <property name="age" type="java.lang.Integer" index="user_index">
            <column name="AGE" />
        </property>
        <!-- 
        	在 Java 中, 代表时间和日期的类型包括: java.util.Date 和 java.util.Calendar. 
        	此外, 在 JDBC API 中还提供了 3 个扩展了 java.util.Date 类的子类: java.sql.Date, java.sql.Time 和 java.sql.Timestamp, 这三个类分别和标准 SQL 类型中的 DATE, TIME 和 TIMESTAMP 类型对                应在标准 SQL 中, DATE 类型表示日期, TIME 类型表示时间, TIMESTAMP 类型表示时间戳, 同时包含日期和时间信息
         -->
        <property name="date" type="timestamp">
            <column name="DATE" />
        </property>
        <property name="desc" formula="(select concat(name,',',date) from user t where t.id = id)"></property>
    	<!-- 映射大对象 -->
    	<property name="oldContent">
    		<column name="OLD_CONTENT" sql-type="text"></column>
    	</property>
    	
    	<!-- 
    	mysql数据库不支持
    	<property name="realContent">
    		<column name="real_Content" sql-type="clob"></column>
    	</property>
    	 -->
    	
    	<property name="image">
    		<column name="image" sql-type="blob"></column>
    	</property>
    </class>
</hibernate-mapping>

    4)通过Hibernate API编程访问操作数据库代码

package com.shma.hibernate.entity;

import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.Test;

public class UserTest {

	@Test
	public void test() {
		//1) 创建一个SessionFactory对象
		SessionFactory sessionFactory = null;
		
		//创建Configuration配置对象,加载hibernate基本配置文件和关系对象映射文件
		Configuration configuration = new Configuration().configure();
		
		//弃用
//		sessionFactory = configuration.buildSessionFactory();
		
		//创建ServiceRegistry服务注册对象,hibernate任何配置和服务都需要在这个对象中注册后才可以使用
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
											.applySettings(configuration.getProperties())
											.buildServiceRegistry();
		
		try {
			sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		} catch (Exception e) {
			e.printStackTrace();
		}

		
		//2) 创建一个Session对象
		Session session = sessionFactory.openSession();
		
		//3) 开启事务
		Transaction transaction = session.beginTransaction();
		
		//4) 执行相关操作
		User user = null;
		try {
			user = new User("马韶华", 23, new Date(new SimpleDateFormat("yyyy-MM-dd").parse("1989-11-10").getTime()));
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		session.save(user);
		
		//5) 提交事务
		transaction.commit();
		
		//6) 关闭Session对象
		session.close();
		
		//7) 关闭SessionFactroy对象
		sessionFactory.close();
	}

}

3、Session

    1)session接口是hibernate向引用程序提供的操作数据库的最主要的接口,提供了基本的增删改和加载java对象的操作;

    2)session具有一个缓存,被称之为hibernate一级缓存;位于缓存中的对象称之为持久化对象;

135514_93BW_239973.png

package com.shma.hibernate.entity;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class UserTest {
	
	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@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();
	}
	
	/**
	 * clear(): 清理缓存
	 */
	@Test
	public void clear() {
		User user = (User) session.get(User.class, 1);
		System.out.println(user);
		User user2 = (User) session.get(User.class, 1);
		System.out.println(user2);
		session.clear();
		
		User user3 = (User) session.get(User.class, 1);
		System.out.println(user3);
	}
	
	/**
	 * reflesh():会强制发送 SELECT 语句, 以使 Session 缓存中对象的状态和数据表中对应的记录保持一致!使数据库中的记录同步到session缓存中
	 */
	@Test
	public void reflesh() {
		
		User user = (User) session.get(User.class, 1);
		System.out.println(user);
		session.refresh(user);
		System.out.println(user);
	}
	
	/**
	 * flush(): 使session缓存中的数据同步到数据库中,为了保存一致,可能会发送对应的SQL语句操作
	 * 
	 * flush()被调用的契机:
	 * 	1) 手动调用session.flush()方法
	 * 	2) 在Transaction对象提交事务之前,会先调用session对象的flush()方法,在提交事务
	 * 	3) 执行HQL或者QBC查询时,如果缓存中持久化对象属性发生变化,则会先flush()一次,以保证查询出来的是最新的数据
	 * 	4) 如果持久化对象主键采用native生成OID(记录的 ID 是由底层数据库使用自增的方式生成),在调用save()方法时,先发生insert()语句,以创建主键id,保证save()方法后主键id是存在的
	 */
	@Test
	public void testSessionFlush() {
//		User user = (User) session.get(User.class, 1);
//		user.setAge(27);
//		user.setName("齐娇娇");
//		
//		session.flush(); //将session缓存中的数据同步到数据库中,执行update方法,但是数据库值没有修改,没有commit
//		System.out.println(user);
		
//		User user = (User) session.get(User.class, 1);
//		
//		//执行HQL或者QBC查询时,如果缓存中持久化对象属性发生变化,则会先flush()一次,以保证查询出来的是最新的数据
//		User user2 = (User) session.createCriteria(User.class).uniqueResult();
//		
//		System.out.println(user == user2);
		
		
		User user3 = new User("孙威", 28, new Date());
		session.save(user3);

	}

	/**
	 * 验证session缓存
	 */
	@Test
	public void testSessionCache() {
		User user = (User) session.get(User.class, 1);
		System.out.println(user);
		
		User user2 = (User) session.get(User.class, 1); //从session缓存中获取,没有查询数据库
		System.out.println(user2);
		
		System.out.println(user == user2);
	}
	
	@After
	public void destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}

}

4、持久化对象状态

    1)站在持久化的角度上,hibernate将对象分为四种状态:

         持久化状态:存在session缓存中,存在数据库记录中,存在OID

            临时状态:不存在session缓存中,不存在数据库记录中,不存在OID    

            游离状态:存在OID,不存在session缓存中,可能存在数据库记录中,一般情况下游离对象是由持久化对象转变而来

            删除状态:存在OID,但是数据库中不存在对应的记录,不存在数据库中,不存在session缓存中

160922_vJ7S_239973.png

package com.shma.hibernate.entity;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
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 UserTest2 {
	
	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	/**
	 * 调用存储过程
	 */
	@Test
	public void testDoWork() {
		session.doWork(new Work() {
			
			@Override
			public void execute(Connection conn) throws SQLException {
				//调用存储过程
			}
		});
	}
	
	/**
	 * evict():从缓存中移除指定的持久化对象
	 */
	@Test
	public void testEvict() {
		User user = (User) session.get(User.class, 8);
		User user2 = (User) session.get(User.class, 9);
		
		user.setName("nihao");
		user2.setName("haha");
		
		session.evict(user);
	
	}
	
	/**
	 * delete: 执行删除操作. 只要 OID 和数据表中一条记录对应, 就会准备执行 delete 操作
	 * 若 OID 在数据表中没有对应的记录, 则抛出异常
	 * 
	 * 可以通过设置 hibernate 配置文件 hibernate.use_identifier_rollback 为 true,
	 * 使删除对象后, 把其 OID 置为  null
	 */
	@Test
	public void testDelete() {
//		User user = new User();
//		user.setId(1);
//		session.delete(user); 
		
		User user = (User) session.get(User.class, 3);
		session.delete(user);
		
		System.out.println(user);
	}
	
	/**
	 * saveOrUpdate:
	 * 	包含了save和update方法,当对象处于游离状态时,则执行save操作,当对象处于持久化状态时,则执行update操作
	 * 判断是否为临时状态:
	 * 	1、Java对象的OID为null
	 * 	2、如果OID在数据库表记录中不存在,则会抛出异常,
	 * 	      除非映射文件中<id>设置了unsaved-value属性,并且java对象中的oid值与设置的unsaved-value值一致
	 */
	@Test
	public void testSaveOrUpdate() {
//		User user = new User("王二", 22, new Date());
//		
//		//user处于游离状态,执行save
//		session.saveOrUpdate(user);
//		
//		// 执行save操作后user转变为持久化对象
//		user.setAge(45);
//		user.setName("王五");
//		
//		session.saveOrUpdate(user);
		
		User user2 = new User("aidai", 10, new Date());
		user2.setId(999);
		session.saveOrUpdate(user2);
	}
	
	/**
	 * update():
	 * 	1) 若更新一个持久化对象,不需要显示调用update方法,因为在调用Transaction的commit方法
	 * 	   时,会调用session的flush()方法
	 * 	
	 * 	2) 若更新一个游离对象,需要显示的调用update方法,把一个游离对象转换为持久化对象
	 * 
	 * 	需要注意的地方:
	 * 	1、无论要更新的游离对象和数据库表中的记录是否一致(持久化对象会先检查,不一致才执行update),都会调用update
	 * 	       操作,如何能让 update方法不再盲目的出发 update 语句呢 ? 在 .hbm.xml 文件的 class 节点设置
	 *    select-before-update=true (默认为 false). 这个属性的含义是在每次update之前先查询一遍数
	 *    据库,如果有修改在执行update,但通常不需要设置该属性. 
	 *    
	 *  2、若数据表中没有对应的记录, 但还调用了 update 方法, 会抛出异常
	 *  
	 * 	3、当 update() 方法关联一个游离对象时, 
	 *    如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常. 因为在 Session 缓存中
	 * 	      不能有两个 OID 相同的对象!
	*/
	@Test
	public void testUpdate() {
		
		// 持久化对象,不需要显示调用update方法
		User user = (User) session.get(User.class, 1);
//		user.setName("齐娇娇");
		
//		session.update(user);
		
//		session.clear();
		
		// 游离状态,必须显示调用update方法
//		user.setName("马韶华");
//		session.update(user);
		
		User user2 = (User) session.get(User.class, 1);
		session.update(user); //session 中已经存在user2
	}
	
	@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();
	}
	
	/**
	 * 1) 执行get()方法:立即执行查询操作加载对象,get为立即检索
	 *    执行load()方法:如不使用该对象,则不会执行查询操作,而是返回一个代理对象,load为延迟检索
	 * 2) 当使用load延时检索时,如果session关闭,可能会抛出LazyInitializationException异常
	 * 3) 如果查询的oid数据库没有对应的数据记录,并且session也没有关闭
	 * 	  	get方法返回null
	 * 	  	load方法如果不使用实体对象属性,加载不会抛出异常,使用的时候会抛出异常
	 * 		
	 */
	@Test
	public void testLoad() {
		User user = (User) session.load(User.class, 10);
		System.out.println(user.getClass().getName());
		
//		session.close();
		System.out.println(user);
	}
	
	/**
	 * get/load:根据一个oid,从数据库中加载一个持久化对象到session缓存中
	 */
	@Test
	public void testGet() {
		User user = (User) session.get(User.class, 10);
		System.out.println(user.getClass().getName());
//		session.close();
		System.out.println(user);
	}
	
	/**
	 * persist(): 和save方法一样保存记录到持久化对象
	 * 和save()方法区别:当对一个OID不为null的对象执行save时,会把对象以一个新oid保存到数据库中,而persist则会抛出异常
	 */
	@Test
	public void testPersist() {
		User user = new User();
		user.setAge(20);
		user.setDate(new Date());
		user.setName("zhangsan");
		user.setId(10); // 抛出异常
		
		session.persist(user);
	}
	
	/**
	 * save():用于将临时对象转换为持久化对象,插入记录
	 * 执行步骤:1) 使一个临时对象保存到session缓存中,转换为持久化对象
	 * 		 2) 为持久化对象生成唯一的UID
	 * 		 3) 执行一条insert语句:在flush缓存时
	 * 		 4) 在save之前的设置id是无效的
	 * 		 5) 在save之后的设置id是不能被修改的,修改会抛出异常
	 */
	@Test
	public void testSave() {
		
		User user = new User();
		user.setAge(20);
		user.setDate(new Date());
		user.setName("zhangsan");
//		user.setId(10); // 设置id是无效的
		
		session.save(user);
		
		System.out.println(user);
		
		user.setId(10); //save()后修改id,抛出异常
	}
	
	@After
	public void destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	   @Test
	public void testWorker() {
		Worker worker = new Worker();
		Pay pay = new Pay();
		pay.setMonthPay(13000.23d);
		pay.setYearDay(5);
		pay.setYearPay(153422.12344d);
		
		worker.setName("马韶华");
		worker.setPay(pay);
		
		session.save(worker);
	}

}

5、映射对象关系

    1)单向多对一

package com.shma.hibernate.entity.n21;

public class Customer {

	private int customerId;
	
	private String customerName;

	public int getCustomerId() {
		return customerId;
	}

	public void setCustomerId(int customerId) {
		this.customerId = customerId;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	@Override
	public String toString() {
		return "Customer [customerId=" + customerId + ", customerName=" + customerName + "]";
	}

}

package com.shma.hibernate.entity.n21;

public class Order {

	private int orderId;
	
	private String orderName;
	
	private Customer customer;

	public int getOrderId() {
		return orderId;
	}

	public void setOrderId(int orderId) {
		this.orderId = orderId;
	}

	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]";
	}
	
}

package com.shma.hibernate.entity.n21;

import static org.junit.Assert.*;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestN21 {

	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@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 destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	@Test
	public void testMany2OneDel() {
//		Order order = (Order)session.get(Order.class, 2); 
//		session.delete(order);
//		
//		session.delete(order.getCustomer());
		
		//在不设定级联关系的情况下, 且 1 这一端的对象有 n 的对象在引用, 不能直接删除 1 这一端的对象
		Customer customer = (Customer) session.get(Customer.class, 2);
		session.delete(customer);
		
		
	}
	
	@Test
	public void testMany2OneUpdate() {
		Order order = (Order)session.get(Order.class, 1);
		order.setOrderName("order-112222");
		order.getCustomer().setCustomerName("AAAAAAAA");
	}
	
	@Test
	public void testMany2OneGet() {
		Order order = (Order)session.get(Order.class, 1);
		System.out.println(order);
		System.out.println(order.getCustomer().getClass());
		
		//如果session被关闭,将抛出异常
//		session.close();

		//延时加载Customer
		Customer customer = order.getCustomer();
		System.out.println(customer);
		
		System.out.println(customer.getClass());
		
	}
	
	@Test
	public void testMany2OneSave() {
//		Customer customer = new Customer();
//		customer.setCustomerName("AAA");
//		
//		Order order01 = new Order();
//		order01.setOrderName("Order-01");
//		
//		Order order02 = new Order();
//		order02.setOrderName("Order-02");
//		
//		order01.setCustomer(customer);
//		order02.setCustomer(customer);
//		
//		//先savecustomer,会saveorder,执行三次insert
//		session.save(customer);
//		session.save(order01);
//		session.save(order02);
		
		
		Customer customer = new Customer();
		customer.setCustomerName("BBB");
		
		Order order01 = new Order();
		order01.setOrderName("Order-03");
		
		Order order02 = new Order();
		order02.setOrderName("Order-04");
		
		order01.setCustomer(customer);
		order02.setCustomer(customer);
		
		//先save order,会save customer,执行三次insert,会执行2次update
		session.save(order01);
		session.save(order02);
		session.save(customer);
		
		
		
	}

}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.shma.hibernate.entity.n21.Customer" table="CUSTOMERS">
        <id name="customerId" type="int">
            <column name="CUSTOMER_ID" />
            <generator class="native" />
        </id>
        <property name="customerName" type="java.lang.String">
            <column name="CUSTOMER_NAME" />
        </property>
        
    </class>
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-7-18 15:21:35 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.shma.hibernate.entity.n21">
    <class name="Order" table="ORDERS">
        <id name="orderId" type="int">
            <column name="ORDER_ID" />
            <generator class="native" />
        </id>
        <property name="orderName" type="java.lang.String">
            <column name="ORDER_NAME" />
        </property>
        
        <!-- 多对一映射关系
        	name:多这一端的一那一端的属性名称
        	class:一端的类型
        	column:一那一端对应在多端的外键名称
         -->
        <many-to-one name="customer" class="Customer">
        	<column name="customer_id"></column>
        </many-to-one>
    </class>
</hibernate-mapping>

    2)双向一对多

package com.shma.hibernate.entity.n21.bath;

import java.util.HashSet;
import java.util.Set;

public class Customer {

	private int customerId;
	
	private String customerName;
	
	/**
	 * 1、声明集合需要使用接口,因为hibernate延迟加载,在获取集合的时候是获取到的hibernate内部集合实例
	 * 2、需要把集合进行初始化, 可以防止发生空指针异常
	 */
	private Set<Order> orders = new HashSet<>();

	public int getCustomerId() {
		return customerId;
	}

	public void setCustomerId(int customerId) {
		this.customerId = customerId;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public Set<Order> getOrders() {
		return orders;
	}

	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}

}

package com.shma.hibernate.entity.n21.bath;

public class Order {

	private int orderId;
	
	private String orderName;
	
	private Customer customer;

	public int getOrderId() {
		return orderId;
	}

	public void setOrderId(int orderId) {
		this.orderId = orderId;
	}

	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]";
	}
	
}

package com.shma.hibernate.entity.n21.bath;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Test12N {

	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@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 destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	@Test
	public void testOne2ManyDel() {
		//在不设定级联关系的情况下, 且 1 这一端的对象有 n 的对象在引用, 不能直接删除 1 这一端的对象
		Customer customer = (Customer) session.get(Customer.class, 1);
		session.delete(customer.getOrders().iterator().next());
	}
	
	@Test
	public void testOne2ManyUpdate() {
		
		Customer customer = (Customer) session.get(Customer.class, 1);
		customer.setCustomerName("CCCCCC");
		
		Customer customer2 = (Customer) session.get(Customer.class, 2);
		customer.getOrders().iterator().next().setCustomer(customer2);
		
	}
	
	@Test
	public void testOne2ManyGet() {
		Customer customer = (Customer) session.get(Customer.class, 1);
		System.out.println(customer.getCustomerName());
		//延时加载
		//返回的多的一端的集合时 Hibernate 内置的集合类型. 
		//该类型具有延迟加载和存放代理对象的功能.
		System.out.println(customer.getOrders().getClass());
		
		//3. 可能会抛出 LazyInitializationException 异常 
//		session.close();
		
		System.out.println(customer.getOrders().iterator().next().getOrderName());
		//再需要使用集合中元素的时候进行初始化. 
	}
	
	@Test
	public void testOne2ManySave() {
		
//		Customer customer = new Customer();
//		customer.setCustomerName("AAA");
//		
//		Order order01 = new Order();
//		order01.setOrderName("Order-01");
//		
//		Order order02 = new Order();
//		order02.setOrderName("Order-02");
//		
//		order01.setCustomer(customer);
//		order02.setCustomer(customer);
//		
//		customer.getOrders().add(order01);
//		customer.getOrders().add(order02);
//		
//		//先savecustomer,会saveorder,执行三次insert
//		session.save(customer);
//		session.save(order01);
//		session.save(order02);
		
		
		Customer customer = new Customer();
		customer.setCustomerName("BBB");
		
		Order order01 = new Order();
		order01.setOrderName("Order-03");
		
		Order order02 = new Order();
		order02.setOrderName("Order-04");
		
		order01.setCustomer(customer);
		order02.setCustomer(customer);
		
		customer.getOrders().add(order01);
		customer.getOrders().add(order02);
		
		//先save order,会save customer,执行三次insert,会执行2次update
		session.save(order01);
		session.save(order02);
		session.save(customer);
		
		
		
	}

}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.shma.hibernate.entity.n21.bath">
    <class name="Customer" table="CUSTOMERS">
        <id name="customerId" type="int">
            <column name="CUSTOMER_ID" />
            <generator class="native" />
        </id>
        <property name="customerName" type="java.lang.String">
            <column name="CUSTOMER_NAME" />
        </property>
        
        <!--
        	1对多映射关系那个属性集合
        	set:映射集合为set类型
        	table:set中集合类型的所对应的表名,需要与多对一中的表名一致
        	inverse:指定由哪一方来维护关联关系. 通常设置为 true, 以指定由多的一端来维护关联关系
        	cascade:级联操作,save-update级联保存并修改关联,delete:级联删除
        	order-by:排序,字段是数据库里面的字段类型
        	name:1的集合属性名称
         -->
        <set name="orders" table="ORDERS" inverse="true" order-by="order_name desc">
			<!-- 执行多的表中的外键列的名字 -->
			<key column="CUSTOMER_ID"></key>
			<!-- 指定映射类型 -->
			<one-to-many class="Order"/>       
        </set>
    </class>
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-7-18 15:21:35 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.shma.hibernate.entity.n21.bath">
    <class name="Order" table="ORDERS">
        <id name="orderId" type="int">
            <column name="ORDER_ID" />
            <generator class="native" />
        </id>
        <property name="orderName" type="java.lang.String">
            <column name="ORDER_NAME" />
        </property>
        
        <!-- 多对一映射关系
        	name:多这一端的一那一端的属性名称
        	class:一端的类型
        	column:一那一端对应在多端的外键名称
         -->
        <many-to-one name="customer" class="Customer">
        	<column name="customer_id"></column>
        </many-to-one>
    </class>
</hibernate-mapping>


转载于:https://my.oschina.net/shma1664/blog/477278

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值