hibernate核心开发接口(4)

1.Configuration

      a)   使用annotation的时候,用AnnotationConfiguration

      b) 主要是进行配置信息管理

      c)   用来产生SessionFactory

      d )  可以在configure方法中指定hibernate配置文件love.xml   

  sessionFactory = new AnnotationConfiguration().configure("love.xml").buildSessionFactory();//读取src目录的下的love.xml文件

      e) 只需要关注一个方法即:buildSessionFactory

2.SessionFactoty里面管理了一系列的连接池,它用来产生Session,然后从池里面拿出一个connection挂到产生的Session上面

         a)  用来产生和管理Session

         b)通常情况下每个应用只需要一个SessionFactory

         C) 除非要访问多个数据库的情况

         D) 关注2个方法即:openSession getCurrentSession

区别:openSession与getCurrentSession的区别?

1.openSession:永远是打开新的Session,需要手动close。

2.getCurrentSession:如果Current Session Context中已经有了Session了,它就会拿当前环境中Session。如果没有,就打开新的Session并存放于Current Session Context中。

  a.getCurrentSession获取的Session会存放于Current Session Context中(在hibernate.cfg.xml可以设置Current Session Context是什么),而openSession不会

  b.getCurrentSession获取的Session提交后会自动close,所以当提交后再次getCurrentSession获取Session时,就不是同一个了

3.对象的三种状态

说明:当一个对象new出来的时候,它是Transient状态。当我们调用save()或saveOrUpdate()的时候,它就变成persistence状态,persistence状态时对象是有id的。当我们关闭session时,persistence状态的对象就会变成detached状态。

3.1.对象的三种状态的区分关键在于

       A)   内存有没有ID (在实际工作中,一般让数据库帮我生成id。但是数据库生成这个id,存在内存中的这个model有没有id呢?)

       B)   缓存中有没有ID(session缓存)

       C)   ID在数据库中有没有

对象的三种状态说明:

a.transient :在内存中new出来一个对象时,内存中没id,缓存中没有id,数据库中也没有id

b.persistence :数据库中有id,缓存中有id(hibernate一级缓存Session中会有),内存中也有id

c.detacted  :数据库中有id,缓存中没有id(hibernate一级缓存Session被清空了),内存中有id

示例代码说明:

@Test
	public void testStudentSave(){
		Student stu = new Student();//当new一个对象的时候,处于transient状态
		stu.setName("gaoweigang");
		stu.setAge(25);
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		session.save(stu);//当save或saveOrUpdate完成后,处于persistence状态
		System.out.println(stu.getId());
		
		session.beginTransaction().commit();//当close完成后,处于detacted状态

		//session.close();因为我们使用的是getCurrentSession,所以就不必显示的关闭Session了
		
	}

图形说明:当save的时候


  

4.Session

     A) 管理一个数据库的任务单元,即session来帮我们管理数据库的增,删,改,查的操作

     B)方法(CRUD)

              I    save()

              Ii   delete()只要数据库中这条记录有id,就可以delete()。

             Iii   update()必须数据库中有这条记录才能update(),所以transient状态的对象不能update,因为数据库中还还没有这个对象的记录。update语句的发出在commit的时候

             Iv   save or update()

             V    load  获取的是一个代理类,这个代理类的父类是被代理类(Student),java使用javassist来直接生成二进制码代理类(也就是不会生成源码,再来编译)

             Vi   get

             Vii  get与load的区别

                    1.数据库中不存在对应记录时表现不一样

                    2.load还回的是代理对象,等到真正用到对象的内容是才发出sql语句

可以通过System.out.println(t.getClass());来证明t所引用的对象的类型不是Teacher类型的

                    3.get直接从数据库加载产生一个对象,不会延迟

可以通过System.out.println(t.getClass());来证明t所引用的对象类型是Teacher类型的

        viii  update

             1. 用来更新detached对象,更新完成后转为peisistent状态

             2.更新transient对象会报错

             3.更新自己指定id的transient对象可以( 前提数据库中要有该id的记录)

             4.persistent状态的对象(当一个persistent状态的对象,里面的值被改变的时候,如果跟原来值相同,那么hibernate就不会发update语句;如果跟原来值不同,hibernate就会发update语句,发的时候会将所有字段都更新)

说明:上面的1234虽然你只更改了部分字段,但是update的时候,会把所有字段update一边,这样的效率很低

             5.只更新更改过的字段(注意:只是在某些情况下,并不是所有情况下,看日志中打印出来sql就知道了)

                    A)第一种: xml设定property标签的update属性,annotation设定@Column的updatable属性(@Conlumn(updatable=false)放到方法上面),不过这种方式很少使用,因为不灵活

                    B)第二种:同一个Session里面可以,夸Session就不行了。在xml中Class上添加dynamic-update ,即<class name="com.bjsxt.model.Student" dynamic-update=”true”>,JPA1.0 Annotation没有对应的属性。

                    C)Hbernate扩展,使用merge同样会执行多余的动作,看日志就知道了

                          1.   同一个session可以,跨session不行,不过可以用merge()

(不重要)

                    D) 使用HQL(EJBQL)(建议)              

Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Student s = (Student) session.get(Student.class, 41);//当save或saveOrUpdate完成后,处于persistence状态
s.setAge(33);
session.beginTransaction().commit();//当close完成后,处于detacted状态

Session session2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
//使用HQL,只会更新指定字段
Query("update Student s set s.name='小熊' where s.id = '41'");
query.executeUpdate();
System.out.println(s.getName());
session2.getTransaction().commit();

         vII .saveOrUpdate();

         vIII. Clear方法

              1.无论是load还是get,都会首先查找session级的缓存(一级缓存),如果没有,才会去数据库查找,调用clear()方法可以强制清除session缓存

         Ix. Flush方法

             1. 可以强制进行从缓存到数据库的同步,默认的情况下是commit的时候进行缓存到数据库的同步;当你进行commit()的时候,默认就进行了flush()

             2.具体在什么时间flush由flushMode决定,每个session都可以设定它的flushMode(flush的模式),所谓fushMode就是指在什么时间进行数据库的同步,flush的模式要在Transaction开始的时候进行设置eg:session.setFlushMode(FlushMode.ALWAYS)设置flush的模式为always,就是无论执行什么话都会进行flush一次;还可以设置为NEVER,表示无论执行什么话都不进行同步(不重要,了解)

6.SchemaExport作用:可以让你在程序里面控制生成建表语句

      <property name="hbm2ddl.auto">update</property>我们现在在数据库中建表用的是这个配置,而实际工作当中可以不用这个配置,不用这个配置的话数据库表不会自动生成,我们可以手动生成; 手动建表时,当执行到下面这条语句是才建表new  SchemaExport(new Configuration().configure()).create(true,true);

其中create第一个参数指定要不要在空中台中显示ddl语句,第二个参数指定建表语句要不要到数据库中执行。这句话会根据hibernate.cfg.xml中的

<mapping resource="com/bjsxt/hibernate/Teacher.hbm.xml"/>    

<mapping class="com.bjsxt.hibernate.model.Student"/>来建立表 

猜你喜欢

转载自weigang-gao.iteye.com/blog/2158289