Hibernate 学习笔记2

来源:互联网 发布:java web和前端开发 编辑:程序博客网 时间:2024/06/14 04:26


将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的测试代码:


@Testpublic 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();// 真正项目中不用关闭}}@Testpublic 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();}}@Testpublic 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 现在想让它是2Class 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();// 真正项目中不用关闭}}@Testpublic 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();// 真正项目中不用关闭}}@Testpublic 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
原创粉丝点击