码迷,mamicode.com
首页 > Web开发 > 详细

Hibernate(二)

时间:2015-09-08 00:35:42      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:

1. 对象的状态

技术分享

技术分享

技术分享

代码


public class StateTest extends HiberanteUtils{
	/**
	 * session.save方法把一个临时状态的对象转化成持久化状态的对象
	 */
	@Test
	public void testSavePerson(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Person person = new Person();
		person.setPname("afds");
		person.setPsex("af");	
		session.save(person);
		
		transaction.commit();
		session.close();
	}
	
	/**
	 * session.update方法可以把一个对象的状态变成持久化状态
	 */
	@Test
	public void testUpdate(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Person person2 = new Person();//临时状态
		person2.setPid(1L);//临时状态
		session.update(person2);//持久化状态
		
		transaction.commit();
		session.close();
	}
	
	/**
	 * 当session.get方法得到一个对象的时候,是不需要再执行 update语句,因为已经是持久化状态
	 * 当一个对象是一个持久化对象的时候,当进行提交的时候,hibernate内部会让该对象和快照进行对比,如果一样,则不发出update语句
	 * 如果不一样,则发出update语句
	 */
	@Test
	public void testGet(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Person person = (Person)session.get(Person.class, 1L);//持久化
		person.setPname("ttkjkjhg");
		
		//session.update(person);
		transaction.commit();
		session.close();
	}
	
	/**
	 * session.clear方法把所有的对象从session中清空
	 */
	@Test
	public void testClear(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Person person = (Person)session.get(Person.class, 1L);
		person.setPname("asd");
		session.clear();//把session中所有的对象清空
		session.update(person);//把对象从脱管状态转化成持久化状态
		
		transaction.commit();
		session.close();
	}
	
	/**
	 * session.evict把一个对象从session中清空
	 */
	@Test
	public void testEvict(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Person person = (Person)session.get(Person.class, 1L);
		person.setPname("asdsss");
		session.evict(person);//脱管状态
		session.update(person);//把对象的状态转化成持久化状态
		
		transaction.commit();
		session.close();
	}
	
	
	/**
	 * 一个对象是否是持久化对象是针对某一个session而言的
	 */
	@Test
	public void testSession(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Person person = (Person)session.get(Person.class, 1L);
		person.setPname("asfd");
		transaction.commit();
		session.close();
		
		session =  sessionFactory.openSession();//94
		transaction =  session.beginTransaction();
		//person.setPname("aaa");//person对象对于94的session来说是一个临时状态的对象
		session.update(person);
		
		transaction.commit();
		session.close();
	}
	
	/**
	 * 当执行transaction.commit的时候,hibernate内部会检查session
	 *    1、如果一个对象为临时状态的对象,则session不会管
	 *    2、如果一个对象是持久化状态的对象,如果有ID值,并且和数据库对应,
	 *    	 那么先把该对象与快照进行对比,如果一致,则什么都不做,如果不一致,则发出update语句
	 *    3、如果一个对象是持久化状态的对象,如果没有ID值,则会发出save语句
	 */
	@Test
	public void testMuplyOption(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Person person = new Person();
		person.setPname("rrr1");
		person.setPsex("asdfasdf");
		
		Person person3 = new Person();
		person3.setPname("rrr2");
		person3.setPsex("asdfasdf");		
		session.save(person);
		
		Person person2 = (Person)session.get(Person.class, 18L);
		person2.setPname("asdfasdf");
		
		transaction.commit();//会检查session中对象的状态。如果是临时对象,session根本不管
		//如果持久话对象的id有值,update.没值,save()
		session.close();
	}
	
	
	@Test
	public void testMutiplyOption2(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Person person = new Person();
		person.setPname("haha1");
		person.setPsex("haha2");
		session.save(person); 
		transaction.commit();
		
		session.evict(person);
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		session.update(person);
		session.clear();
		transaction.commit();
		session.close();
	}
}

2. 一对多的单项关联

2.1. 数据库表和实体类关系

技术分享

2.2. Classes映射文件中cascade、inverse、外键的配置


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="cn.itcast.hiberate.sh.domain.Classes">
		<id name="cid" length="5" type="java.lang.Long">
			<generator class="increment"></generator>
		</id>
		<property name="cname" length="20" type="java.lang.String"></property>
		
		<property name="description" length="100" type="java.lang.String"></property>
		<!-- 
			set元素对应类中的set集合
			通过set元素使classes表与student表建立关联
			   key是通过外键的形式让两张表建立关联
			   one-to-many是通过类的形式让两个类建立关联
			
			【cascade】 级联
			   * save-update
			   	1、当保存班级的时候,对学生进行怎么样的操作
			   	     如果学生对象在数据库中没有对应的值,这个时候会执行save操作
			   	     如果学生对象在数据库中有对应的值,这个时候会执行update操作
			   * delete:删除班级的时候删除学生
			   * all:save-update,delete
			
			【inverse】  维护关系
			   * true      不维护关系     
			   * false     维护关系
			   * default   false
			   inverse所在的映射文件类。Classes是否维护Classes与student之间的关系,如果不维护cid为null			   
		 -->
		
		<!-- cascade表示,在对classes进行操作的时候对班级进行cascade中值的什么操作 -->		
		<set name="students" cascade="all" inverse="true">
			<!-- key是用来描述外键-->
			<key>
				<column name="cid"></column>
			</key>
			<one-to-many class="cn.itcast.hiberate.sh.domain.Student"/>
		</set>
	</class>
</hibernate-mapping>



技术分享


技术分享

2.3. 代码体现


package cn.itcast.hibernate.sh.test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.annotations.Type;
import org.junit.Test;

import cn.itcast.hiberate.sh.domain.Classes;
import cn.itcast.hiberate.sh.domain.Student;
import cn.itcast.hibernate.sh.utils.HiberanteUtils;

/**
 * 1、新建一个班级
 * 2、新建一个学生
 * 3、新建一个班级的时候同时新建一个学生
 * 4、已经存在一个班级,新建一个学生,建立学生与班级之间的关系
 * 5、已经存在一个学生,新建一个班级,把学生加入到该班级
 * 6、把一个学生从一个班级转移到另一个班级
 * 7、解析一个班级和一个学生之间的关系
 * 8、解除一个班级和一些学生之间的关系
 * 9、解除该班级和所有的学生之间的关系
 * 10、已经存在一个班级,已经存在一个学生,建立该班级与该学生之间的关系
 * 11、已经存在一个班级,已经存在多个学生,建立多个学生与班级之间的关系
 * 12、删除学生
 * 13、删除班级
 *     删除班级的时候同时删除学生
 *     在删除班级之前,解除班级和学生之间的关系
 * @author Think
 *
 */
public class OneToManySingleTest extends HiberanteUtils{
	@Test
	public void testSaveClasses(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		Classes classes = new Classes();
		classes.setCname("传智上海云一期");
		classes.setDescription("很牛");
		session.save(classes);
		transaction.commit();
		session.close();
	}
	
	
	
	@Test
	public void testSaveStudent(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		Student student = new Student();
		student.setSname("班长");
		student.setDescription("老牛:很牛");
		session.save(student);
		transaction.commit();
		session.close();
	}
	
	@Test
	public void testSaveClasses_Student(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Classes classes = new Classes();
		classes.setCname("传智上海云二期:");
		classes.setDescription("很牛X");
		
		Student student = new Student();
		student.setSname("班长");
		student.setDescription("老牛:很牛X");
		
		session.save(student);
		session.save(classes);
		transaction.commit();
		session.close();
	}
	
	/**
	 * 在保存班级的时候,级联保存学生
	 */
	@Test
	public void testSaveClasses_Cascade_Student_Save(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Classes classes = new Classes();
		classes.setCname("传智上海云三期:");
		classes.setDescription("很牛XX");
		
		Student student = new Student();
		student.setSname("班长");
		student.setDescription("老牛:很牛XX");
		
		Set<Student> students = new HashSet<Student>();
		students.add(student);
		
		//建立classes与student之间的关联
		classes.setStudents(students);
		session.save(classes);
		transaction.commit();
		session.close();
	}
	
	/**
	 * 在保存班级的时候,级联更新学生
	 */
	@Test
	public void testSaveClasses_Cascade_Student_Update(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Classes classes = new Classes();
		classes.setCname("传智上海云四期:");
		classes.setDescription("很牛XXX");
		
		Student student = (Student)session.get(Student.class, 1L);
		
		student.setSname("班秘");
		
		Set<Student> students = new HashSet<Student>();
		students.add(student);
		
		classes.setStudents(students);
	
		session.save(classes);
		transaction.commit();
		session.close();
	}
	
	/**
	 * 更新班级的同时保存学生
	 */
	@Test
	public void testUpdateClasses_Cascade_Student_Save(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Classes classes = (Classes)session.get(Classes.class, 5L);
		
		Student student = new Student();
		student.setSname("班花");
		student.setDescription("稀有人物");
		
		classes.getStudents().add(student);//因为已经有班级了,所以先获取班级的学生,再添加学生
		//因为classes是持久化对象,所以不用update()
		transaction.commit();
		session.close();
	}
	
	
	/**
	 * 更新班级的同时更新学生
	 */
	@Test
	public void testUpdateClasses_Cascade_Student_Update(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		Classes classes = (Classes)session.get(Classes.class, 5L);
		Set<Student> students = classes.getStudents();//为cid为5的班级的所有的学生
//		for(Student student:students){
//			student.setDescription("压力山大");
//		}  快照
		transaction.commit();
		session.close();
	}
	
	/**
	 * 一个错误的演示---在classes映射文件中删除了cascade="save-update"
	 * 保存班级的同时保存学生
	 * ------------------------------------
	 * 在客户端试图通过保存班级保存学生,但是由于在配置文件中针对students没有cascade属性,没有级联,
	 * 所以导致classes中的student成为临时状态的对象了,hibernate不允许这种情况出现。
	 * 把session.save/update一个对象的操作为显示操作,级联对象的操作为隐式操作
	 */
	@Test
	public void testSaveClasses_Cascade_Student_Save_Error(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Classes classes = new Classes();
		classes.setCname("传智上海云六期:");
		classes.setDescription("很牛XXXXXX");
		
		Student student = new Student();
		student.setSname("班长XXXXXX");
		student.setDescription("老牛:很牛XXXXXX");
		
		Set<Student> students = new HashSet<Student>();
		students.add(student);
		
		//建立classes与student之间的关联
		classes.setStudents(students);
		session.save(classes);
		transaction.commit();
		session.close();
	}
	
	
	/**
	 * 【方式一】
	 * 已经存在一个班级,新建一个学生,建立学生与班级之间的关系
	 * ==============================================================
	 * 新建立一个学生,在学生表的cid自断处处,添加这个学生班级的id,即建立了关系。
	 *    通过更新班级级联保存学生  cascade起作用,负责:已经存在一个班级,新建一个学生
	 *    建立班级和学生之间的关系  inverse起作用,负责:建立学生与班级之间的关系
	 * ==============================================================
	 * 	用inverse属性代替了外键,面向对象的思考方式。因为在student类中不能出现cid
	 * 	inverse用来维护两个表之间的关系
	 */
	@Test
	public void testSaveStudent_R_1(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		Student student = new Student();
		student.setSname("技术班长");
		student.setDescription("大神");
		Classes classes = (Classes)session.get(Classes.class, 1L);
		
		classes.getStudents().add(student);
		
		transaction.commit();
		session.close();
	}
	
	/**【方式二】
	 * 	Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=?
		Hibernate: select max(sid) from Student
		Hibernate: select students0_.cid as cid0_1_, students0_.sid as sid1_, students0_.sid as sid1_0_, students0_.sname as sname1_0_, students0_.description as descript3_1_0_ from Student students0_ where students0_.cid=?
		Hibernate: insert into Student (sname, description, sid) values (?, ?, ?)
		更新关系的操作
		Hibernate: update Student set cid=? where sid=?
	 */
	@Test
	public void testSaveStudent_R_2(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		Student student = new Student();
		student.setSname("技术班长");
		student.setDescription("大神");
		Classes classes = (Classes)session.get(Classes.class, 1L);
		
		session.save(student);
		
		classes.getStudents().add(student);//只有建立了关系inverse才能起作用。若没这行cid为null
		
		transaction.commit();
		session.close();
	}
	
	/**
	 * 已经存在一个学生,新建一个班级,把学生加入到该班级
	 */
	@Test
	public void testSaveClasses_R(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Classes classes = new Classes();
		classes.setCname("老毕基础加强班");
		classes.setDescription("必看,杀手锏");
		
		Student student = (Student)session.get(Student.class, 2L);
		Set<Student> students = new HashSet<Student>();
		students.add(student);
		classes.setStudents(students);
		
		session.save(classes);
		transaction.commit();
		session.close();
	}
	
	/**
	 * 把一个学生从一个班级转移到另一个班级
	 * 	即:先解除班级和学生之间的关系,再建立学生和另外一个班级之间的关系
	 * 	Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=?
		Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=?
		Hibernate: select student0_.sid as sid1_0_, student0_.sname as sname1_0_, student0_.description as descript3_1_0_ from Student student0_ where student0_.sid=?
		Hibernate: select students0_.cid as cid0_1_, students0_.sid as sid1_, students0_.sid as sid1_0_, students0_.sname as sname1_0_, students0_.description as descript3_1_0_ from Student students0_ where students0_.cid=?
		Hibernate: select students0_.cid as cid0_1_, students0_.sid as sid1_, students0_.sid as sid1_0_, students0_.sname as sname1_0_, students0_.description as descript3_1_0_ from Student students0_ where students0_.cid=?
		Hibernate: update Student set cid=null where cid=? and sid=? //解除
		Hibernate: update Student set cid=? where sid=? //建立
		简单操作:直接把外键5变为6就可以完成
	 */
	@Test
	public void testTransformClass(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		//Classes classes5 = (Classes)session.get(Classes.class, 5L);
		Classes classes6 = (Classes)session.get(Classes.class, 6L);
		Student student = (Student)session.get(Student.class, 1L);
		//classes5.getStudents().remove(student); //只是移除了关系,并不是删除学生
		classes6.getStudents().add(student);//建立新关系
		
		transaction.commit();
		session.close();
	}
	
	/**
	 * 解除一个班级和一些学生之间的关系
	 */
	
	@Test
	public void testR_Some(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		Classes classes = (Classes)session.get(Classes.class, 1L);
		Set<Student> students = classes.getStudents();
//		for(Student student:students){
//			if(student.getSid().longValue()==6||student.getSid().longValue()==7){
//				students.remove(student);
//			}
//		}
		//set-->list
		List<Student> sList = new ArrayList<Student>(students);
		for(int i=0;i<sList.size();i++){
			if(sList.get(i).getSid().longValue()==6||sList.get(i).getSid().longValue()==7){
				sList.remove(sList.get(i));
				i--;
			}
		}
		
		students = new HashSet<Student>(sList);
		classes.setStudents(students);
		/**
		 * 增强for循环只能修改一次
		 *   1、用普通的for循环
		 *   2、新建一个set集合,把原来的set集合要保留的数据存放到新的set集合中
		 */
		transaction.commit();
		session.close();
	}
	
	/**解除班级一和所有学生之间的关系
	 * classes.setStudents(null);直接把班级针对student的集合设置为null
	 */
	@Test
	public void testRealseAll(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		Classes classes = (Classes)session.get(Classes.class, 1L);
		
//方式一		Set<Student> students = classes.getStudents();
//		students.clear();   //为何不用removeAll(Conllection c)
		//方式2
		classes.setStudents(null); 
		transaction.commit();
		session.close();
	}
	
	/**
	 * 删除学生
	 */
	@Test
	public void testDeleteStudent(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Student student = (Student)session.get(Student.class, 8L);
		session.delete(student);
		
		transaction.commit();
		session.close();
	}
	
	
	/**
	 * 在删除班级之前,解除班级和学生之间的关系
	 */
	@Test
	public void testDeleteClasses(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Classes classes = (Classes)session.get(Classes.class, 5L);
		//classes.setStudents(null);//如果不维护关系。inverse=true
		session.delete(classes);//班级维护了关系,所以在删除班级的时候,自然也解除了学生和班级的关系
		
		transaction.commit(); 
		session.close();
	}
	
	/**
	 * 级联删除班级5的同时删除学生
	 */
	@Test
	public void testDeleteClasses_Cascade(){
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		Classes classes = (Classes)session.get(Classes.class, 5L);
		session.delete(classes);
		
		transaction.commit();
		session.close();
	}
}



2.4. 常见错误分析

技术分享

技术分享

3. hibernate基础知识总结

1、hibernate的组成部分
    	持久化类
    	    实现对应的序列化接口
    	    必须有默认的构造函数
    	    持久化类的属性不能使用关键字
    	    标示符
 		
	映射文件
 	    类型
		java类型和hibernate类型
 	    主键的产生器
		increment identity  assigned uuid
 	    id  prototype
 	    set集合
 		cascade  对象与对象之间的关系,和外键没有关系
 		inverse  对象与外键之间的关系
  		
	配置文件
  	    数据库的链接信息
  	    存放了映射文件的信息
  	    其他信息:hibernate内部功能的信息
  		显示sql语句:<property name="show_sql">true</property>
		生成表的:<property name="hbm2ddl.auto">update</property>


2、hibernate的流程
    Configuraction
      	加载了配置文件
		Configuration configuration = new Configuration();
		configuration.configure();
    SessionFactory(接口)
        配置文件的信息、映射文件的信息、持久化类的信息全部在SessionFactory
		特点:线程安全、单例
		SessionFactory sessionFactory = configuration.buildSessionFactory();
    Session(接口)
		Session session = sessionFactory.openSession();
        1、crud的操作都是由session完成的
        2、事务是由session开启的
        3、两个不同的session只能用各自的事务
        4、session决定了对象的状态
			一个对象在session中,肯定是持久化的
        5、创建完一个session,相当于打开了一个数据库的链接
    Transaction
		Transaction transaction = session.beginTransaction();
		transaction.commit();
        1、事务默认不是自动提交的
			* jdbc的事务默认是自动提交的
        2、必须由session开启
        3、必须和当前的session绑定(两个session不可能共用一个事务)

3、对象的状态的转化

4、hibernate的原理:
     	根据客户端的代码,参照映射文件,生成sql语句,利用jdbc技术进行数据库的操作











Hibernate(二)

标签:

原文地址:http://my.oschina.net/ilaoda/blog/502555

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!