Hibernate 学习笔记2


将Session与本地线程绑定


//由于session是单线程对象 所以实际中一般会把它与线程绑定
//保证它的单线程性

public static Session getCurrentSession(){
return sf.getCurrentSession();
}

这个需要在hibernate.cfg.xml中配置

<!-- 配置将hibernate与本地session绑定 保证session是单线程对象 -->
<property name="hibernate.current_session_context_class">thread</property>


实体类的三种状态:

1.    临时态:(无id  与session无关)

User user =new User();

user.setName(“aaa”);

user.setPwd(“123”);

session.save(user);

2.托管态(有id 与session无关)

User user =new User();

user.setId(2);

session.delete(user)

3.持久态(有id  与session有关)

User user=session.get(User.class,1);


Hibernate缓存:



验证一级缓存(默认打开):

执行过程:(存的不是对象 而是对象值,再以某个值作为这个存储的索引,以便下次的寻找 比如id然后再组装成一个对象返回)

查询只做了一次

			// 5 具体的crud操作
			Student stu1=session.get(Student.class, 3);			
			System.out.println(stu1);			
			Student stu2 = session.get(Student.class, 3);
			System.out.println(stu2);


一级缓存执行过程:




建立一对多 和多对多关系

 都知道数据库中 有一对多和多对多的关系

       比如学生对班级 1对多  学生对课程 就是多对多

一共3步骤:

1.    编写实体类

*在1的一方 需要包含多的一方 也就是之间的关联关系

*在多的一方 需要包含另一方Set<>集合也就是之间的聚合关系

2.    配置xx.hbm.xml文件(需要双向配置)

 <many-to-onename="cla" column="class_id" class="com.lsy.entity.Class"></many-to-one>

<!--这个many-to-one配置的是它代表与班级之间的 它是多的关系

      配置在多的一方

    name属性 为Student类中Class的名称

    column为表中外键的列名

    class 为1的一方的实体类的路径

 -->

 

 

    <setname="stuSet"cascade="save-update">

    <keycolumn="class_id"> 

    </key>

    <one-to-manyclass="com.lsy.entity.Student"/>

   

    </set>

 

    <!-- 这个set标签配置的是 它与学生之间它是1的关系(记住hibernate里面是双向维护外键不能只单纯只配置一方)

配置cascade属性:后可以少写一部分代码 在做级联保存 添加 这种时可以直接把多的一方 添加少的一方即可

也就是这部分代码:

           Studentstu =new Student();

           stu.setAge(21);

           stu.setName("asdf");

           stu.setSex("男");                 

           Classcla=session.get(Class.class, 1);

//cla.getStuSet().add(stu)

           stu.setCla(cla);

可以少写注释了的代码 配置后hibernate帮我们封装

key标签配置外键的列名

最后加上一个one-to-many标签 加上多的一方的class

     -->

完整配置见之后代码块

 

学会了一对多的配置后 对于多对多应该看一下就能明白(直接见代码块)

3.    在核心文件中引入最后测试


student.hbm.xml

<?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>
	<!-- 配置表与实体间的一一对应关系(mapping) -->
	<class name="com.lsy.entity.Student" table="t_student">
		<!-- 配置主键 -->
		<id name="id" column="id">
			<!--配置主键生成策略 native表示主键自动增长 -->
			<generator class="native"></generator>
		</id>
		<!-- 配置其他的字段 name 实体类属性名称 column表字段名称 -->
		<property name="name" column="name"></property>
		<property name="sex" column="sex"></property>
		<property name="age" column="age"></property>

		<!--配置1对多(多的一方) -->
		<many-to-one name="cla" column="class_id" class="com.lsy.entity.Class"></many-to-one>

		<!--配置多对多 -->
		<set name="courseSet" table="student_course" cascade="save-update,delete">
			<key column="stu_id"></key>
			<many-to-many column="course_id" class="com.lsy.entity.Course"></many-to-many>

		</set>


	</class>


</hibernate-mapping>

Student.java


package com.lsy.entity;

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

public class Student {

	private Integer id;
	private String name;
	private String sex;
	private Integer age;

	private Class cla;

	private Set<Course> courseSet=new HashSet<Course>();

	public Set<Course> getCourseSet() {
		return courseSet;
	}

	public void setCourseSet(Set<Course> courseSet) {
		this.courseSet = courseSet;
	}

	public Class getCla() {
		return cla;
	}

	public void setCla(Class cla) {
		this.cla = cla;
	}

	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 String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

}





class.hbm.xml

<?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="com.lsy.entity.Class" table="t_class" >
    <id name="cid" column="id"> 
    <generator class="native"></generator>
    
    </id>

	<!-- 配置其他的字段
		name 实体类属性名称
		column表字段名称
	 -->
	<property name="name" column="name"></property>
	
	<!-- 这个many-to-one 配置的是它代表与系之间的 它是多的关系-->
  <many-to-one name="dep" column="dep_id" class="com.lsy.entity.Department"></many-to-one>

	<!-- 配置1对多(多的一方): -->
	<set name="stuSet" cascade="save-update,delete">
	<key column="class_id">	
	</key>
	<one-to-many class="com.lsy.entity.Student"/>
	</set>  
    </class>
    </hibernate-mapping>

Class.java


package com.lsy.entity;

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

public class Class {
	
	private int cid;
	private String name;
	
	private Set<Student> stuSet=new HashSet<Student>();
	
	private Department dep;
		
	public Department getDep() {
		return dep;
	}
	public void setDep(Department dep) {
		this.dep = dep;
	}
	public int getCid() {
		return cid;
	}
	public void setCid(int cid) {
		this.cid = cid;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Student> getStuSet() {
		return stuSet;
	}
	public void setStuSet(Set<Student> stuSet) {
		this.stuSet = stuSet;
	}
	

}


做级联crud的测试代码:


	@Test
	public void testOneToMany() {

		SessionFactory sf = HibernateUtils.getSessionFactory();

		Session session = sf.openSession();
		Transaction tran;
		try {
			tran = session.beginTransaction();
			
			Student stu = new Student();//瞬时态对象
			stu.setAge(21);
			stu.setName("asdf");
			stu.setSex("男");
			Class cla = session.get(Class.class, 1);
			stu.setCla(cla);
			session.save(stu);

			tran.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
			sf.close();// 真正项目中不用关闭

		}

	}
	

	@Test
	public void testOneToManyDelete() {

		SessionFactory sf = HibernateUtils.getSessionFactory();

		Session session = sf.openSession();
		Transaction tran;
		try {
			tran = session.beginTransaction();
			Class cla = session.get(Class.class, 1);				
			session.delete(cla);

			tran.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
			sf.close();

		}

	}
	

	@Test
	public void testOneToManyUpdate() {

		SessionFactory sf = HibernateUtils.getSessionFactory();

		Session session = sf.openSession();
		Transaction tran;
		try {
			tran = session.beginTransaction();
			Student stu = session.get(Student.class,1);
			stu.setName("Benjamin");
			//原本stu的class_id是1 现在想让它是2
			Class cla = session.get(Class.class, 2);
			cla.getStuSet().add(stu);
			
			stu.setCla(cla);
			
			//session.save(stu); 持久态的对象会自动更新 意思不用save 它也会帮你更新

			tran.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
			sf.close();// 真正项目中不用关闭

		}

	}
	
	
	
	
	
	
	@Test
	public void testManyToMany1() {

		SessionFactory sf = HibernateUtils.getSessionFactory();

		Session session = sf.openSession();
		Transaction tran = session.beginTransaction();
		try {

			Student stu = session.get(Student.class, 2);// 持久态对象
			Course course1 = session.get(Course.class, 1);// 持久态对象
			Course course2 = session.get(Course.class, 3);
			stu.getCourseSet().add(course1);
			stu.getCourseSet().add(course2);
			session.save(stu);

			tran.commit();

		} catch (Exception e) {
			e.printStackTrace();
			tran.rollback();
		} finally {
			session.close();
			sf.close();// 真正项目中不用关闭

		}

	}

	@Test
	public void testManyToMany2() {

		SessionFactory sf = HibernateUtils.getSessionFactory();

		Session session = sf.openSession();
		Transaction tran = session.beginTransaction();
		try {

			Student stu = new Student();
			stu.setId(5);
			stu.setName("jack");
			stu.setAge(20);
			stu.setSex("男");

			Course course1 = new Course();
			course1.setName("JAVA");
			course1.setCredit(4);
			Course course2 = new Course();
			course1.setName("Python");
			course1.setCredit(2);
			stu.getCourseSet().add(course1);
			stu.getCourseSet().add(course2);
			session.save(stu);

			tran.commit();
		} catch (Exception e) {
			e.printStackTrace();
			tran.rollback();
		} finally {
			session.close();
			sf.close();// 真正项目中不用关闭

		}

	}



无论是一对多还是多对多做级联保存时 都需要在set 设置cascade 的值为 “save-update”

执行上面的这个测试方法时testOneToManyUpdate()

做修改时有这问题 (他会修改两次 显然有一次是多余的原因是因为双方都维护了外键)



解决方式:为提高性能 会让其中的一方放弃维护外键,一般让一的那一方,  inverse属性 值为:false(默认) 代表不放弃 true代表放弃

  <!-- 配置1对多(多的一方): -->
<set name="stuSet" cascade="save-update,delete" inverse="true" >

而一对多做删除时 比如删除班级 然后删除此班级的所有学生 可以在cascade 中设置 delete 多个值之间有,逗号分开  调用方法session.delete();


多对多时不需要调用session.delete 而是调用其中一方的Set集合的remove方法 使用delete时除了将第三张表中两对象的ID删除在原来的表中也会删除。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值