• Hibernate学习笔记


    Hibernate

    一、hibernate是什么

    1. 一种框架,一种orm框架
      (objext relation mapping)对象关系映射框架。
    2. hibernate处于项目的持久层位置,又叫持久化框架。
    3. hibernate实际上是对jdbc进行轻量级的封装。

    二、需求

    1. 切换数据库需要重写编写sql。
    2. 使用jdbc操作数据库语句编写比较麻烦。
    3. 让程序员只关注业务逻辑,不再关心数据库。

    三、快速入门案例

    使用手动配置hibernate方式开发一个hibernate项目,完成相关操作。

    开发流程

    1. 创建一个项目
    2. 画出简单的项目框架图
    3. 引入Hibernate包
    4. 开发Hibernate三种方式
    • 由Domain object --> mapping --> db。 (官方推荐)
    • 由DB开始,用工具生成Mapping的Domain object。(使用较多)
    • 由映射文件开始。

    我们使用第二种方式
    首先在hibernate数据库下创建student表

    create table student(
    id int primary key,
    name varchar(20) not null,
    age varchar(20) not null,
    );
    

    5.开发domain对象 和对象关系映射
    对象关系映射文件,用于指定domain对象和表的映射关系,该文件的取名有规范,domain对象hbm.xml,一般和domain对象同一包下。

    <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE hibernate-mapping PUBLIC
         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
         "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
      
     <hibernate-mapping package="com.sun.hibernate.model">
         <class name="Student">
             <id name="id"></id>
             <property name="name"></property>
             <property name="age"></property>
         </class>
     </hibernate-mapping>
    

    6.手动配置hibernate.cfg.xml文件,该文件用于配置连接的数据库类型,diver,用户名,密码....同时管理对象关系映射文件和该文件的名称,这个文件一般放在src目录下。

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
           "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
           "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    	
    	<hibernate-configuration>
       <session-factory>
        
       <!-- Database connection settings -->
       <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
       <property name="connection.url">jdbc:mysql://localhost/hibernate</property>
       <property name="connection.username">root</property>
       <property name="connection.password"></property>
            
       <!-- JDBC connection pool (use the built-in) -->
       <!-- <property name="connection.pool_size">1</property> -->
            
       <!-- SQL dialect -->
       <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
            
       <!-- Echo all executed SQL to stdout -->
       <property name="show_sql">true</property>
            
       <!-- Enable Hibernate's automatic session context management -->
       <!--<property name="current_session_context_class">thread</property>-->
            
       <!-- Drop and re-create the database schema on startup -->
       <!-- <property name="hbm2ddl.auto">create</property> -->
            
       <!-- Disable the second-level cache -->
       <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        
       <mapping resource="com/sun/hibernate/model/Student.hbm.xml"/>
          
         </session-factory>
     </hibernate-configuration>
    

    7. 创建对应的student模型

    package com.sun.hibernate.model;
    
    public class Student {
    	private int id;
    	private String name;
    	private int age;
    	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 int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	
    
    }
    
    

    8.测试方法(向数据库中添加一条数据)

    package com.sun.hibernate.model;
    
    
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.classic.Session;
    
    public class StudentTest {
    	public static void main(String[] args){
    		Student s = new Student();
    		s.setId(1);
    		s.setName("s1");
    		s.setAge(2);
    		
    		//1.创建Configuration ,该对象用于读取hibernate.cfg.xml,并完成初始化
    		Configuration  cfg = new Configuration();
    		//2.创建SessionFactory<这是一个会话工厂,是一个重量级对象>
    		SessionFactory sf = cfg.configure().buildSessionFactory();
    		//3.创建一个session,相当于jdbc Connection<不是jsp中的那个session>
    		Session session = sf.openSession();
    		//4.对hibernate而言,要求程序员在进行增加,删除,修改时必须使用事物提交
    		session.beginTransaction();
    		session.save(s);	//insert into ...  <sql语句被hibernate封装了>
    		session.getTransaction().commit();
    		session.close();
    		sf.close();
    	}
    }
    
    

    直接运行StudentTest就可以将数据插入到数据库中了。

    四、 hibernate缓存原理

    详细信息

    1.session缓存(一级缓存)

    Session内置不能被卸载,Session的缓存是事务范围的缓存(Session对象的生命周期通常对应一个数据库事务或者一个应用事务)。
    一级缓存中,持久化类的每个实例都具有唯一的OID。

    2.二级缓存

    第二级缓存是可选的,是一个可配置的插件,默认下SessionFactory不会启用这个插件。
    Hibernate提供了org.hibernate.cache.CacheProvider接口,它充当缓存插件与Hibernate之间的适配器。

    什么样的数据适合存放到第二级缓存中?   

    1. 很少被修改的数据   
    2. 不是很重要的数据,允许出现偶尔并发的数据   
    3. 不会被并发访问的数据   
    4. 常量数据   
      不适合存放到第二级缓存的数据?   
    5. 经常被修改的数据   
    6. 绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发   
    7. 与其他应用共享的数据。

    Hibernate查找对象如何应用缓存?
    当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;
    查不到,如果配置了二级缓存,那么从二级缓存中查;
    如果都查不到,再查询数据库,把结果按照ID放入到缓存删除、更新、增加数据的时候,同时更新缓存。

    五、 Query接口

    通过Query接口我们可以完成更加复杂的查询任务

    快速入门

    /*获取query应用【这里student不是表,而是domain】
    where后面的条件可以是一个类的属性名,也可以是表的字段,按照hibernate规定,我们还是应该使用类的属性名*/
    	Query query = session.createQuery("from Teacher  where id = 2");
    	//通过list方法获取结果,这个list会自动将封装成对应的dommain
    	//所以我们jdbc进行二次封装的工作没有
    	List<Teacher> list = query.list();
    		for(Teacher tea: list){
    			System.out.println(tea.getName() + "  " + tea.getAge());
    		}
    

    六、 criteria接口简单使用

    快速入门

    Criteria cri = session.createCriteria(Teacher.class).setMaxResults(4);
    			List<Teacher> list = cri.list();
    			for(Teacher tea:list){
    				System.out.println(tea.getId() + "  " + tea.getName());
    			}
    

    七、HQL

    (hibernate query language)

    1.需求

    在现有的只是基础上,对对象的批量删除,修改,查询还不能很方便的实现。

    模拟创建表

    2.list

    查询所有对象

    List<Student> list =  session.createQuery("from Student").list();
    

    3.uniqueResult

    如果检索一个对象,明确知道最多只有一个,则建议使用该方法。
    具体用法:

    Student stu =  (Student) session.createQuery(" from Student where sid = 20040001").uniqueResult();
    

    4.HQL常见用法

    distinct的用法:(用于过滤重复记录)

    List<Object[]> list =  (List<Object[]>)session.createQuery(" select distinct ssex,sage from Student").list();
    

    between...and的用法

    List<Object[]> list =  (List<Object[]>)session.createQuery(" select distinct sname,ssex,sage from Student where sage between 22 and 24").list();
    

    in 和 not in的用法

    List<Student> list = session.createQuery("from Student where sdept in ('数学系','计算机系')").list();
    

    group 和 having 和 order by
    group用法:(查询各个系的学生的平均年龄)

    List<Object[]> list = session.createQuery("select avg(sage),sdept from Student group by sdept").list();
    

    having的使用(显示人数大于等于2的系)

    List<Object[]> list = session.createQuery("select count(*),sdept from Student group by sdept having count(*) >= 2").list();
    

    (查询各个系女生的人数)

    List<Object[]> list = session.createQuery("select count(*),sdept from Student where ssex='M' group by sdept").list();
    

    order by用法(查询所有学生的成绩拼按照成绩高低排序)

    List<Object[]> list = session.createQuery("select student.sname,course.cname,grade from Studcourse order by grade DESC").list();
    

    查询计算机系共有多少学生
    如果返回一列数据,取出数据是必须用Object,而不是Object[]

    List<Object[]> list = session.createQuery("select count(*) from Student where sdept='计算机系'").list();
    

    查询总成绩是多少

    List<Object[]> list = session.createQuery("select sum(grade) from Studcourse").list();
    

    查询课程号为1001的课程名称,最高分和最低分

    List<Object[]> list = session.createQuery("select course.cname,min(grade),max(grade) from Studcourse where course.cid=1011").list();
    

    查询各科大于80分的学生的名字,科目,分数

    List<Object[]> list =session.createQuery("select student.sname,course.cname,grade from Studcourse where grade > 80").list();
    

    计算各科大于80分的的学生数量

    List<Object[]> list = session.createQuery("select course.cname,count(*) from Studcourse where grade>80 group by course.cid").list();
    

    5.HQL分页技术

    查询所有学生成绩进行高低排序并只分页显示。

    //获取页数
    int pageCount = Integer.parseInt(session.createQuery("select count(*) from Studcourse").uniqueResult().toString()) /3 +1;
    System.out.println("一共有"+pageCount+"页");
    //开始查询
    for(int i = 0; i < pageCount; i++){
    	List<Object[]> list = session.createQuery("select student.sname,course.cname,grade from Studcourse order by grade DESC").
    			setFirstResult(i*3).setMaxResults(3).list();
    	for(int j = 0; j < list.size(); j ++) {
    		Object[] obj = list.get(j);
    		System.out.println(obj[0].toString() + "  " + obj[1].toString() + " " + obj[2].toString());
    	}
    	System.out.println("*******第"+(i+1)+"页**********");
    }
    

    6.参数绑定

    好处:
    1.可读性高
    2.效果好
    3.防止sql注入漏洞

    一般写法:

    List<Student> list = session.createQuery("from Student where sage = 22 and sname = '张三'").list();
    

    参数绑定写法:
    如果我们的参数是冒号形式给出的,则可以这样写:

    List<Student> list = session.createQuery("from Student where sage=:sage andsname=:sname").setString("sage", "22").setString("sname", "张三").list();
    

    如果我们的参数是问号形式给出的,则可以这样写:

    List<Student> list = session.createQuery("from Student where sage=? and sname=?").setString(0, "22").setString(1, "张三").list();
    

    将绑定分开写:

    Query query = session.createQuery("from Student where sage=? and sname=?");
    query.setInteger(0, 22);
    query.setString(1, "张三");
    List<Student> list = query.list();
    

    映射文件中得到hql语句

    hibernate提供了一种更加灵活的查询方法。
    把hql语句配置到对象关系映射文件

    <query name="myquerytest">
        from Student
    </query>
    

    八、hibernate对象的三种关系映射

    1. one-to-one: 身份证<---->人 丈夫<--->妻子
    2. one-to-many: 部门<--->员工
    3. many-to-one:员工<--->部门
    4. many-to-many:学生<--->老师(尽量避免)
      (在实际开发过程中,如果出现了多对多的关系,我们应该尽量装换为两个一对多或者多对一的关系,这样程序好控制,同时不会有冗余)

    1.one-to-one

    一对一两种方式:
    (1)基于主键的一对一
    (人<--->身份证 one<--->one)

    //Person.java,略去了相关的get/set方法
    private Integer id;
    private String name;
    private IdCard idCard;
    
    //Person.hbm.xml
    <hibernate-mapping package="com.sun.hibernate.model">
      <class name="Person">
    	<id name="id" type="java.lang.Integer">
    		<!-- 我们手动分配id -->
    		<generator class="assigned" />
    	</id>
    	<property name="name" type="java.lang.String">
    		<column name="name" length="128" />
    	</property>
    	<!-- 这里配置person和idcard属性是一对一关系 -->
    	<one-to-one name="idCard"></one-to-one>
    </class>
    </hibernate-mapping>
    
    //IdCard.java,略去了相关的get/set方法
    private Integer id;
    private Date validata;
    private Person person;
    
    //IdCard.hbm.xml
    <hibernate-mapping package="com.sun.hibernate.model">
      <class name="IdCard">
    	<id name="id" type="java.lang.Integer">
    		<!-- 因为我们这里是基于主键的one-to-one, 所以我们使用外键策略 -->
    		<generator class="foreign">
    			<!-- 这里值,是指跟那个属性ont-to-one -->
    			<param name="property">person</param>
    		</generator>
    	</id>
    	<property name= "validata" type="java.util.Date">
    		<column name="validata" />
    	</property>
    	<!-- constrained设置为true才会使得在数据提交的时候同时提交相关的关联关系,在此例中如果没有IdCard表将不会有外键-->
    	<one-to-one name="person" constrained="true" />
    </class>
    </hibernate-mapping>
    

    (2)基于外键的一对一
    (人<--->身份证 one<--->one)

    //Person.java,略去了相关的get/set方法(和基于主键的Person.java一致)
    private Integer id;
    private String name;
    private IdCard idCard;
    
    //Person.hbm.xml(和基于主键的Person.hbm.xml一致)
    <hibernate-mapping package="com.model.one2one">
    	<class name="Person">
    		<id name="id" type="java.lang.Integer">
    			<!-- 我们手动分配id -->
    			<generator class="assigned" />
    		</id>
    		<property name="name" type="java.lang.String">
    			<column name="name" length="128" />
    		</property>
    		<!-- 这里配置person和idcard属性是一对一关系 -->
    		<one-to-one name="idCard"></one-to-one>
    	</class>
    </hibernate-mapping>
    
    //IdCard.java,略去了相关的get/set方法(和基于主键的IdCard.java一致)
    private Integer id;
    private Date validate;
    private Person person;
    
    //IdCard.hbm.xml(注意与基于主键的IdCard.hbm.xml的区别)
    <hibernate-mapping package="com.model.one2one">
    	<class name="IdCard">
    		<!-- 基于外键的one-one -->
    		<id name="id" type="java.lang.Integer">
    			<generator class="assigned" />
    		</id>
    		<property name="validate" type="java.util.Date">
    			<column name="validate" />
    		</property>
    		<many-to-one name="person" unique="true" />
    	</class>
    </hibernate-mapping>
    

    //测试函数
    //添加一组Person/idcard
    Session session = null;
    Transaction ts = null;
    try {
        session = MySessionFactory.getSessionFactory().openSession();
        ts = session.beginTransaction();
        Person p1 = new Person();
        p1.setId(100);
        p1.setName("小明");
        IdCard idCard = new IdCard();
        idCard.setId(2015001);//如果是基于主键的one-to-one关系则不用设置
        idCard.setValidate(new Date());
        idCard.setPerson(p1);
        session.save(p1);
        session.save(idCard);
        ts.commit();
    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        if(session != null && session.isOpen()){
            session.close();
        }
    }
    

    2.one-to-many

    配置文件示例
    (学生<----->选课表 one<--->many)

    //Student.hbm.xml配置文件
    //Student.java定义Studcourse代码:private Set<Studcourse> studcourses = new HashSet<Studcourse>(0);
    <set name="studcourses" inverse="true">
        <key>
            <column name="sid" />
        </key>
        <one-to-many class="com.domain.Studcourse" />
    </set>
    
    //Studcourse.hbm.xml配置文件
    //Studcourse定义Student代码:private Student student;
    <many-to-one name="student" class="com.domain.Student" fetch="select">
        <column name="sid" />
    </many-to-one>
    

    3.many-to-many

    学生<--->课程
    many-to-many在实际开发过程中,如果出现这种多对多的关系,我们应该尽量转换为两个一对多或者多对一的关系,这样程序好控制,同时不会有冗余。
    所以学生<--->课程我们转换为学生<--->选课记录表(many<--->one) 选课记录表<--->课程(one<--->many)

    学生表(student)

    sid sname sdept
    2001 李华 计科

    选课表(studcourse)

    idstudcourse sid cid grade
    1 2001 A101 87

    课程表(course)

    cid cname ccredit
    A101 java编程课 3
    如上所示,我们使用选课表将学生<--->课程多对多的关系化解成了两个多对一的关系。

    代码及配置

    //Student.java
    private Integer sid;
    private String sname;
    private String sdept;
    private Set<Studcourse> studcourses = new HashSet<Studcourse>(0);
    
    //Student.hbm.xml
    <hibernate-mapping>
        <class name="com.domain.Student" table="student" catalog="course">
            <id name="sid" type="java.lang.Integer">
                <column name="sid" />
                <generator class="identity" />
            </id>
            <property name="sname" type="string">
                <column name="sname" length="20" not-null="true" />
            </property>
            <property name="sdept" type="string">
                <column name="sdept" length="10" not-null="true" />
            </property>
            <set name="studcourses" inverse="true">
                <key>
                    <column name="sid" />
                </key>
                <one-to-many class="com.domain.Studcourse" />
            </set>
        </class>
    </hibernate-mapping>
    

    //Studcourse.java
    private Integer idstudCourse;
    private Course course;
    private Student student;
    private Integer grade;
    
    <hibernate-mapping>
        <class name="com.domain.Studcourse" table="studcourse" catalog="course">
            <id name="idstudCourse" type="java.lang.Integer">
                <column name="idstudCourse" />
                <generator class="identity" />
            </id>
            <many-to-one name="course" class="com.domain.Course" fetch="select">
                <column name="cid" />
            </many-to-one>
            <many-to-one name="student" class="com.domain.Student" fetch="select">
                <column name="sid" />
            </many-to-one>
            <property name="grade" type="java.lang.Integer">
                <column name="grade" />
            </property>
        </class>
    </hibernate-mapping>
    
    

    Course.java
    private Integer cid;
    private String cname;
    private Integer ccredit;
    private Set<Studcourse> studcourses = new HashSet<Studcourse>(0);
    
    //Course.hbm.xml
    <hibernate-mapping>
        <class name="com.domain.Course" table="course" catalog="course">
            <id name="cid" type="java.lang.Integer">
                <column name="cid" />
                <generator class="identity" />
            </id>
            <property name="cname" type="string">
                <column name="cname" length="40" not-null="true" />
            </property>
            <property name="ccredit" type="java.lang.Integer">
                <column name="ccredit" />
            </property>
            <set name="studcourses" inverse="true">
                <key>
                    <column name="cid" />
                </key>
                <one-to-many class="com.domain.Studcourse" />
            </set>
        </class>
    </hibernate-mapping>
    
    //Test.java
    Student stu = new Student();	
    stu.setSname("王宝强");
    stu.setSsex("M");
    stu.setSdept("表演系");
    stu.setSage(32);
    stu.setSaddress("河南");
    
    
    Course course = new Course();
    course.setCid(1016);
    course.setCname("asp.net");
    course.setCcredit(4);
    
    Studcourse stucourse = new Studcourse();
    stucourse.setIdstudCourse(20009);
    stucourse.setStudent(stu);
    stucourse.setCourse(course);
    stucourse.setGrade(79);
    
    Session session = null;
    Transaction ts = null;
    try {
    	session = HibernateUtil.openSession();
    	ts = session.beginTransaction();
    	
    	session.save(course);
    	
    	session.save(stu);	
    	
    	session.save(stucourse);
    	
    	ts.commit();
    } catch (Exception e) {
    	if(ts != null){
    		ts.rollback();
    	}
    	throw new RuntimeException(e.getMessage());
    }finally{
    	//关闭session
    	if(session != null && session.isOpen()){
    		session.close();
    	}
    }
    

    九、 对象的三种状态

    1. 瞬时状态(transient)

    数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器回收,一般是new出来且且与session没有关联的对象。

    2.持久状态(persitent)

    数据库中有数据与之对应,与当前session有关联,并且相关联的session没有关闭,事物没有提交;持久对象状态发生改变,在事务提交时会影响数据库(hibernate能检测得到)

    3.托管状态/游离状态(datached)

    数据库中有数据与之对应,但当前没有session与之关联;脱管状态发生改变时,hibernate不能检测到。

    Student stu = new Student();	//stu就是瞬时状态
    		stu.setSname("王宝强");
    		stu.setSsex("M");
    		stu.setSdept("表演系");
    		stu.setSage(32);
    		stu.setSaddress("河南");
    		
    		Session session = null;
    		Transaction ts = null;
    		try {
    			session = HibernateUtil.openSession();
    			ts = session.beginTransaction();
    			
    			session.save(stu);	
    			//stu既处于session管理下,
    			//同时stu被保存到数据库中,因此stu此时是持久态
    			stu.setSname("唐国强");//hibernate能检测到,并且会提交到数据库中去
    			ts.commit();
    			session.close();
    			//这是stu被保存到数据库中,没有处于session的管理之下
    			//此时stu就是脱管状态(游离态)
    			
    		} catch (Exception e) {
    			if(ts != null){
    				ts.rollback();
    			}
    			throw new RuntimeException(e.getMessage());
    		}finally{
    		}
    

    十、级联操作

    所谓级联操作就是说,当你进行某个操作(添加、修改、删除),就有hibernate自动给你完成。
    比如删除一个学生那么这个学生相应的选课表也要被删除。
    配置(配置cascade对应的属性就可以实现相应的级联操作)cascade:create,merge,save-update,delete,lock,refresh,evict,replicate;默认值为none,也可以设置为all
    级联操作一般在one-to-one和one-to-many中比较有用,在many-to-one和many-to-many中没有什么意义。

    <set name="studcourses" inverse="true" cascade="save-update">
    

    十一、 其他

    1. 什么是pojo类,他有什么要求?

    • pojo类和一张表对应
    • 一般放在com.XXX.domain下
    • pojo需要一个主键属性(用于标示一个pojo对象)
    • 除了主键属性,它还应当有其他属性,属性的访问权限为private
    • 提供get/set方法
    • 它应当有一个无参构造方法(hibernate反射)
    • pojo类其实就是一个javaBean(有时也叫Data对象)

    2. hibernate核心类和接口
    1. configuration类
    2. 读取配置文件
    3. 管理关系映射文件
    4. 加载hibernate的驱动,url,用户
    5. 管理hibernate配置信息

    3. hibernate.cfg.xml
    4. 对象关系映射文件
    5. SessionFactory接口(会话工厂)
    1. 可以缓存sql语句和数据(称为session级缓存)
    2. 是一个重量级的类,因此需要保证一个数据库有一个SessionFactory
    6. 通过SessionFactory获取Session的两个方法
    1. openSession()是获取一个新的Session
    2. getCurrentSession()获取和当前绑定的session,换言之,在同一个线程中,我们获取的session是同一个session。(如果希望使用getCurrentSession需要配置hibernate.cfg.xml)

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

    3.如何选择
    如果在同一个线程中,保证使用同一个session,则使用getCurrentSession(),如果在同一个线程中需要使用不同的Session,则使用opentSession()
    4. openSession() 和 getCurrentSession()的区别
    * 通过getCurrentSession获取的session在事务提交以后会自动关闭,通过openSession获取的session则必须手动关闭,但是我们建议不管什么形式获取的session都进行判断后手动关闭。
    * 如果是通过getCurrentSession()获取session进行查询时,也要进行事务提交。

    7. 本地事务:针对一个数据库的事物
    全局事务:跨数据库的事物(jta)

    8. session接口:
    主要功能和作用
    1. session一个实例代表与数据库的一次操作。(当然一次操作可以使crud组合)
    2. session实例是通过SessionFactory获取,用完需要关闭。
    3. session实例是线程不同步的(不安全),因此要保证在同一线程中使用,可以用getCurrentSession()
    4.session可以看做是持久化管理器,它与持久化操作相关的接口。

    get() 和load()区别
    1. get()方法直接返回实体类,如果找不到数据则返回null。load()会返回一个实体代理对象(当前这个对象可以自动转化为实体对象)。但当代理对象被调用时,如果数据不存在,就会抛出org.hibernate.ObjectNotFoundException异常。
    2. load先到缓存(session缓存/二级缓存)中去查,如果没有则返回一个代理对象(不马上到DB中去找),等后面使用这个代理对象操作的时候,才到DB中去查询,这就是我们常说的load在默认情况下支持延迟加载(lazy--->我们可以在配置文件中关闭懒加载功能).

    懒加载

    简述:当我们查询一个对象的时候,在默认情况下返回的只是该对象普通属性,当用户使用哪个对象属性是才会向数据库中发出一次查询,这种现象我们成为懒加载现象
    禁用懒加载功能
    方法一:(配置文件中进行禁用)

    <class name="Student" lazy="false">
    

    方法二:(显示初始化,Hibernate.initizlize(代理对象))

    Hibernate.initlalize(stu.getDept());
    

    方法三:(通过过滤器openSessionview解决)
    3. get先到缓存(session缓存/二级缓存)中去查,如果没有就到DB中去查(即马上发出sql)。总之,如果你确定DB中有这个对象就用load(),不确定就用get()(这样效率高)

  • 相关阅读:
    40 +必不可少的前端Web开发备忘单
    web前端开发必读的HTML5的书籍
    Java String的内存机制
    使用C#通过Oracle.DataAccess连接Oracle,部署时需要注意版本问题
    CI(CodeIgniter)的"Disallowed Key Characters."异常处理
    开源软件许可协议简介
    读《考拉小巫的英语学习日记》有感
    vi的复制、粘贴、查找、删除等常用命令
    读《马云创业启示录》有感
    jQuery ajax 同步失效?
  • 原文地址:https://www.cnblogs.com/snail-lb/p/5671717.html
Copyright © 2020-2023  润新知