Hibernate学习笔记(四) — session的产生方式 与 一对多关系映射

一、session的创建

Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例,但Session不是线程安全的。


每次openSession,产生的都是一个新的session,相当于创建一个新的连接。但是有很多时候,并不希望这样。比如在淘宝购物,在付账的一瞬间,至少有三件事情发生,转账,仓库数据变化,购物历史记录。而这三件事有必须在同一事务下。自然我们会联想都ThreadLocal<Session> 来解决这个问题。

Hibernate提供了getCurrentSession()方法来解决这一问题,详细看ThreadLocalSessionContext类源码


思考:为什么ThreadLocal(context)里放的是Map,且Map的key是sessionFactory,value是session?

1.一个sessionFactory代表一个数据库连接,这样Map的key存放sessionFactory肯定也就是一个(对于一个数据库),自然也就是一个session,而使用Map也就是为了多个数据库连接。

2.在web操作时希望 request 和 response 是一个连接,这样设计保证了这点,无论怎么误操作,即使又新建了一个session,但是sessionfatory不变,也只会把原理的session覆盖,还是保证了在一个session里。

这样的做法,起到了一个双保险的作用,IBM以前就是ThreadLocal<Session>。

getCurrentSession使用

在hibernate.cfg.xml中添加

<property name="current_session_context_class">thread</property>

注意:如果用该方法(当前线程先产生session),CRUD必须都在事务下进行,在transaction.commit()时,session自动关闭。

缺点:把session和transaction绑定在一起了.在transaction提交之后,再想进行数据库操作就不行了(工作流)

Spring与Hibernate结合后,就把这个提交方式改了,事务提交与session关闭分开。

二、one2many 一对多关系映射

2.1单向

classes类

public class Classes implements Serializable{

	private Long cid;
	private String name;
	private Set<Student> students;
}
student类

public class Student implements Serializable{

	private Long sid;
	private String name;
}
映射文件

<class name="Classes" table="CLASSES">
		<id name="cid">
			<generator class="native"></generator>
		</id>
		<property name="name"></property>
		<!-- 
			set元素针对的就是Classes类中的Set属性
			cascade  级联操作
			   null  默认值
			   save-update
			      	在保存classes对象的时候,针对student进行保存或者更新的操作
			      	在更新classes对象的时候,针对student进行保存或者更新的操作
			   all
			   delete
			inverse  关系操作
			   default:classes维护classes与student之间的关系
			   true:   classes不维护classes与student之间的关系
			   false:  classes维护classes与student之间的关系
		 -->
		<set name="students" cascade="save-update" inverse="true">
		<!-- key:外键,告诉hibernate通过cid来建立classes与student的关系 -->
			<key column="cid"></key>
			<one-to-many class="Student"/>
		</set>
	</class>
<class name="Student" table="STUDENT">
		<id name="sid">
			<generator class="native"></generator>
		</id>
		<property name="name"></property>
	</class>
测试类,主要看hibernate发出的sql语句

public class One2manyTest {

	private Session session;
	private Transaction transaction;
	
	@Before
	public void init(){
		session = HibernateUtils.openSession();
		transaction = session.beginTransaction();
	}
	/**
	 * 一对多的单向操作
	 */

	@Test
	public void testSaveClass_cascade_SaveStudent(){
		Classes classes = new Classes();
		classes.setName("软件");
		Set<Student> students = new HashSet<Student>();
		Student student = new Student();
		student.setName("A");
		students.add(student);
		classes.setStudents(students);
		session.save(classes);//需要设置cascade
	}
	
	/**
	 * sessin.flush的时候
	 *    1、检查一级缓存中所有的持久化状态的对象
	 *        判断发出insert语句或者update语句
	 *    2、检查所有的持久化对象的关联对象
	 *         如果关联对象是由临时状态转化过来的,则对关联对象发出insert语句
	 *         如果关联对象是从数据库中提取出来的,则对照副本,决定是否发出update语句
	 */
	@Test
	public void testUpdateClass_cascade_UpdateStudent(){

		Classes classes = (Classes) session.get(Classes.class, 3L);
		Set<Student> students = classes.getStudents();
		for(Student student : students){
			student.setName("AA");
		}
		session.update(classes);
	}
	
	/**
	 * 维护关联关系
	 * 更新班级  级联  保存学生
	 */
	@Test
	public void testUpdateClass_cascade_SaveStudent(){
		Classes classes = (Classes)session.get(Classes.class, 3L);
		
		Student student = new Student();
		student.setName("cc");
		//建立班级与学生之间的关系
		classes.getStudents().add(student);
		
		
		//看发出sql语句
		/**
		 * Hibernate: 
		    update
		        STUDENT 
		    set
		        cid=? 
		    where
		        sid=?
		    维护关联关系:inverse:false由本身维护,true由对方维护,默认false
		    inverse设置为true,有Student维护关联关系,就不发送最后的update语句
		 */
	}

	@After
	public void destory(){
		transaction.commit();
		session.close();
	}
}
2.2双向

public class Student implements Serializable{

	private Long sid;
	private String name;
	private Classes classes;
	}

	<class name="Student" table="STUDENT">
		<id name="sid">
			<generator class="native"></generator>
		</id>
		<property name="name"></property>
		<!-- 
			name:Student类属性
			column:外键
		 -->
		<many-to-one cascade="save-update" name="classes" column="cid" class="Classes">
		</many-to-one>
	</class>

测试类

public class One2manyTest {

	private Session session;
	private Transaction transaction;
	
	@Before
	public void init(){
		session = HibernateUtils.openSession();
		transaction = session.beginTransaction();
	}
	
	/**
	 * Hibernate: 
	    insert 
	    into
	        STUDENT
	        (name, cid) 
	    values
	        (?, ?)
	        连带cid直接插进去,所以如果用多的一个方,来维护关系,操作就是本身,没有维护外键一说
	 */
	@Test
	public void testSaveStudent_cascade_SaveClasses(){
		Student student = new Student();
		student.setName("haha");
		Classes classes = new Classes();
		classes.setName("软件1302");
		
		//通过学生建立关系
		student.setClasses(classes);//注意给Student设置cascade
		
		session.save(student);
	}
	
	/**
	 * 把sid为3的学生,从cid为3的班级转到cid为4的班级
	 * Hibernate: 
	    update
	        STUDENT 
	    set
	        name=?,
	        cid=? 
	    where
	        sid=?
	 */
	@Test
	public void testTransformClasses(){
		Student student = (Student) session.get(Student.class, 3L);
		Classes classes = (Classes) session.get(Classes.class, 4L);
		student.setClasses(classes);
		//session.update(student);
	}

	//移除一个班级的学生
	@Test
	public void testRemoveStudentFromClasses1(){
		Student student = (Student) session.get(Student.class, 7L);
		Classes classes = (Classes) session.get(Classes.class,3L);
		Set<Student> students = classes.getStudents();
		students.remove(student);//并没有删除,这里需要注意,因为此时是由多的一方维护关联关系,一的一方维护失效
		session.update(classes);
		
	}
	@Test
	public void testRemoveStudentFromClasses2(){
		Student student = (Student) session.get(Student.class, 7L);
		Classes classes = (Classes) session.get(Classes.class,3L);
		student.setClasses(null);
		
	}
	
	@After
	public void destory(){
		transaction.commit();
		session.close();
	}
}

总结:

inverse与cascade的关系

cascade指的是级联操作,操作的是一般属性,指的是对象与对象的操作

inverse指的是关系操作,针对的是外键

一对的多的双向:

当多的一方维护关系时,不会发出更新关系的update语句,而一的一方维护关关系时需要发出维护关系的update语句,一般情况下,多的一方维护关系效率比较高

一对多描述的是对象与集合之间(一对多)的关系或者对象与对象(多对一)之间的关系。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值