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,内存中也有id
c.detacted :数据库中有id,缓存中没有id,内存中有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"/>来建立表