hibernate(五)核心开发接口与对象的三种状态
一、Configuration
1、AnnotationConfiguration
2、进行配置信息的管理
3、configure()方法通过传入一个配置文件来使用例:new Configutayion.configure("myhibernateconfig.xml")...如果不传入配置文件则默认为hibernate.cfg.xml
二、SessionFactory
1、维护着数据库的连接池,当它产生一个session的时候就是从数据库连接池中捡出一个连接交给这个session。
2、getCurrentSession():如果当前上下文环境已经有一个session了就直接获取这个sesssion如果没有则创建一个session,(在session提交前即执行session.getTransaction().commit()之前拿到的是同一个session,而当session提交后session会关闭,再拿到就是新的session)。事务提交自动close()
4、上下文:通过在配置文件中指定hibernate.current_session_context_class属性
有四个值:jta | thread | managed | custom.Class
jta(java transaction api):java中用来管理事务的API(分布式数据库事务管理)
如果值为thread当执行getCurrentSession()时就会从当前线程找session,如果没有找到session则创建session
3、openSession():永远会创建一个新的session。需要close()。
(注:先openSession()获取一个session1,然后getCurrentSession()获取一个session2,这两个session不会==。因为session1标记为需要关闭而session2标记不可关闭,两个session的实现类不同)
三、对象三种状态
Transient(临时状态):是刚刚new出来。内存中一个对象,没id,缓存中也没有(session缓存)
Persistent(持久化状态):执行sava()等其他方法之后会转成Persistent状态,该状态有id。内存中有,缓存中有,数据库中有,有id。
Detached(脱离管理状态):close()等其他方法之后会转成该状态。内存有,缓存没有(脱离管理了),数据库有,id有
例:
Teacher t = new Teacher();// t:Transient状态 t.setName("test1");// t:Transient状态 t.setTitle("title1");// t:Transient状态 Session session = sf.openSession(); session.beginTransaction(); session.save(t);
System.out.println(t.getId());// t:Persistent状态 session.getTransaction().commit();
System.out.println(t.getId());// t:Detached状态 session.close();
2、三种状态的区别
(1)有没有id;
如果没有id一定是Transient状态
(2)id在数据库中有没有;
(3)id在内存中有没有(session缓存);
四、Session
1、管理一个数据库的任务单元(session来帮我们管理,进行curd)
2、方法(CURD)
(1)delete
执行delete()方法会转成Transisent状态(参考三状态图),只要有id号就可以删除
(2)load(Class arg0 , Serialirable arg1),第一个参数是类,第二个是主键
例:Teacher t = (Teacher)session.load(Teacher.class , 1);
注:
Teacher t = (Teacher)session.load(Teacher.class , 1); session.getTransaction().commint(); System.out.println(t.getName());
这种写法会抛出LazyInitializationException:could not initialize proxy - no Session异常
原因是load返回代理对象,当执行load方法的时候并不会发出sql语句,而是等到执行取出t对象的属性的时候(比如执行getName()的时候)才执行。而例子中执行getName()的时候session事务已经提交了
(3)get(Class arg0 , Serialirable arg1)
例:Teacher t = (Teacher)session.load(Teacher.class , 1);
当执行get方法的时候会马上发出sql语句,然后从数据库中取出值装到对象t中。
(4)update
(a)用来更新detached对象,更新完成后转为persistent状态
(b)更新transistent对象会报错
(c)更新自己设定id的transistent对象可以
Teacher t = new Teacher(); t.setId(1); // 此时t是Transient状态 t.setName("test1_test1"); Session session1 = sf.getCurrentSession(); session1.beginTransaction(); session1.update(t);// 此时t是persistent状态,如果t没有setid则会抛出异常 session1.getTransaction().commit();
(d)Persistent状态的对象只要更改对象的某个属性就会在session commit的时候发生更新
(e)更新部分更改的字段
(1)在不想参与update属性上添加注解@Column(updatable=false)
配置文件中可以在property节点上加上update="false"属性,这种方式不灵活很少用
(2)在实体类对应的配置文件如Student.hbm.xml中<class name="Student">节点上添加属性dynamic-update="true"即:<class name="Student" dynamic-update="true">
这时候就会只改更新的属性
注:(注释内容)
Session session = sf.getCurrentSession(); session.beginTransaction(); Student s = (Student)session.get(Teacher.class, 1); s.setName("test1_test");// 此时更新时将会只修改name即SQL:update student set name=? where id=? session.getTransaction().commit(); s.setName("test1_test1"); // Session session1 = sf.getCurrentSession(); session1.beginTransaction(); session1.update(s);// 此时更新时将会修改所有属性即SQL:update student set name=? , age=? , sex=? where id=? /** * 之所以第一处setName()只修改name而第二处会修改所有属性,是因为在第一处hibernate会有对比的对象会知道只有name属性修改了, * 但是在第二处由于hibernate没有对比的对象所以不知道有哪些属性修改了所以会修改全部的属性
*
* 如果想只修改name的属性的话可以使用merge()方法,这个方法会先执行select再update */ session1.getTransaction().commit();
(3)使用HQL语句(建议)
(5)saveOrUpdate(Object obj)
(6)clear()
无论是load还是get都会首先从session缓存中查找(一级缓存),如果没有,才会去数据库查找,调用clear()方法会强制清除session缓存
Session session = sf.getCurrentSession(); session.beginTransaction(); Teacher t = (Teacher)session.load(Teacher.class, 1);// 此时并不执行sql System.out.println(t.getName());// 此时会执行语句 session.clear(); Teacher t2 = (Teacher)session.get(Teacher.class, 1);// 此时并不执行sql System.out.println(t2.getName());// 如果不加上session.clear()则此时不会执行sql语句因为session缓存中已经存在了Teacher对象, // 如果加上了的话则执行sql,因为clear方法会清除session缓存 session.getTransaction().commit();
(7)flush()
可以强制进行从内存到数据库的同步。
Session session = sf.getCurrentSession(); session.beginTransaction(); Teacher t = (Teacher)session.load(Teacher.class, 1);// 此时并不执行sql t.setName("test1"); session.flush(); t.setName("test2"); /** * 如果不加上session.flush()则只执行一次sql,而加上则会执行两次,第一此修改为test1第二次修改为test2 */ session.getTransaction().commit();
五、SchemaExport
new SchemaExport(new AnnotationConfiguration().configure()).create(true , true);