Hibernate核心接口

Configuration(AnnotationConfiguration)

作用:进行配置信息的管理

目标:用来产生SessionFactory

可以在configure方法中指定hibernate配置文件,默认(不指定)时在classpath下加载hibernate.cfg.xml文件

加载默认的hibernate的配置文件

sessionFactory factory =new AnnotationConfiguration().configure().buildSessionFactory();

加载指定hibernate的配置文件

sessionFactory factory  = newnnotationConfiguration().configure("hibernate.xml").buildSessionFactory();


SessionFactory

作用:主要用于产生Session的工厂(数据库连接池)

当它产生一个Session时,会从数据库连接池取出一个连接,交给这个Session

Session session= sessionFactory.getCurrentSession();

       并且可以通过这个Session取出这个连接

getCurrentSession():表示当前环境没有Session时,则创建一个,否则不用创建

openSession():表示创建一个Session(3.0以后不常用),使用后需要关闭这个Session

两方法的区别:

①、openSession永远是每次都打开一个新的Session,而getCurrentSession不是,是从上下文找、只有当前没有Session时,才创建一个新的Session

②、OpenSession需要手动close,getCurrentSession不需要手动close,事务提交自动close

③、getCurrentSession界定事务边界

所指的上下文是指hibernate配置文件(hibernate.cfg.xml)中的“current_session_context_class”所指的值:(可取值:jta|thread|managed|custom.Class)

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

常用的是:

①、thread:是从上下文找、只有当前没有Session时,才创建一个新的Session,主要从数据界定事务

②、jta:主要从分布式界定事务,运行时需要Application Server来支持(Tomcat不支持)

③、managed:不常用

④、custom.Class:不常用


Session

save()

session.save(Object)

session的save方法是向数据库中保存一个对象,这个方法产生对象的三种状态

delete()

session.delete(Object)

Object对象需要有ID

对象删除后,对象状态为Transistent状态

load()

格式: Session.load(Classarg0,Serializable arg1) throws HibernateException

    arg0:需要加载对象的类,例如:User.class

    arg1:查询条件(实现了序列化接口的对象)。如果是数值类类型,则hibernate会自动使用包装类,

    此方法返回类型为Object,但返回的是代理对象。

    执行此方法时不会立即发出查询SQL语句。只有在使用对象时,它才发出查询SQL语句,加载对象。

    因为load方法实现了lazy(称为延迟加载、赖加载)

    延迟加载:只有真正使用这个对象的时候,才加载(才发出SQL语句)

    hibernate延迟加载实现原理是代理方式。

    采用load()方法加载数据,如果数据库中没有相应的记录,则会抛出异常对象不找到(org.hibernate.ObjectNotFoundException)

Get()    

格式:Session.get(Classarg0,Serializable arg1)方法

 arg0:需要加载对象的类,例如:User.class

 arg1:查询条件(实现了序列化接口的对象):如果是基数类型,则hibernate会自动转换成包装类

 返回值:此方法返回类型为Object,也就是对象,再强行转换为需要加载的对象就可以了。

 如果数据不存在,则返回null;

 注:执行此方法时立即发出查询SQL语句。

load()与get()区别

①不存在对应记录时表现不一样;

② load返回的是代理对象,等到真正使用对象的内容时才发出sql语句,这样就要求在第一次使用对象时,要求session处于open状态,否则出错

③get直接从数据库加载,不会延迟加载

get()和load()只根据主键查询,不能根据其它字段查询,如果想根据非主键查询,可以使用HQL

update()

①用来更新detached对象,更新完成后转为为persistent状态(默认更新全部字段)

②更新transient对象会报错(没有ID)

③更新自己设定ID的transient对象可以(默认更新全部字段)

④persistent状态的对象,只要设定字段不同的值,在session提交时,会自动更新(默认更新全部字段)

⑤更新部分更新的字段(更改了哪个字段就更新哪个字段的内容)

a)方法1:update/updatable属性

xml:设定<property>标签的update属性,设置在更新时是否参与更新

<property name="name" update="false"/>

注意:update可取值为true(默认):参与更新;false:更新时不参与更新

annotateon:设定@Column的updatable属性值,true参与更新,false:不参与更新

@Column(updatable=false)

public StringgetTitle(){return title;}

注意:此种方法很少用,因为它不灵活

b)方法2:dynamic-update属性

注意:此方法目前只适合xml方式,JAP1.0annotation没有对应的

在实体类的映射文件中的<class>标签中,使用dynamic-update属性,true:表示修改了哪个字段就更新哪个字段,其它字段不更新,但要求是同一个session(不能跨session),如果跨了session同样会更新所有的字段内容。

<class name="com.bjsxt.Student" dynamic-update="true">

          代码:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. @Test  
  2.   public void testUpdate5() {     
  3.       Session session =sessionFactory.getCurrentSession();  
  4.       session.beginTransaction();  
  5.       Student s=(Student)session.get(Student.class1);  
  6.       s.setName("zhangsan5");  
  7.       //提交时,会只更新name字段,因为此时的s为persistent状态  
  8.       session.getTransaction().commit();  
  9.       s.setName("z4");  
  10.       Session session2 =sessionFactory.getCurrentSession();  
  11.       session2.beginTransaction();  
  12.       //更新时,会更新所有的字段,因为此时的s不是persistent状态  
  13.       session2.update(s);  
  14.       session2.getTransaction().commit();   
  15. }  

如果需要跨session实现更新修改的部分字段,需要使用session.merget()方法,合并字段内容

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. @Test  
  2.   public void testUpdate6() {     
  3.       Session session =sessionFactory.getCurrentSession();  
  4.       session.beginTransaction();  
  5.       Student s=(Student)session.get(Student.class1);  
  6.       s.setName("zhangsan6");  
  7.       session.getTransaction().commit();  
  8.       s.setName("z4");  
  9.       Session session2 =sessionFactory.getCurrentSession();  
  10.       session2.beginTransaction();  
  11.       session2.merge(s);  
  12.       session2.getTransaction().commit();  
  13. }  

这样虽然可以实现部分字段更新,但这样会多出一条select语句,因为在字段数据合并时,需要比较字段内容是否已变化,就需要从数据库中取出这条记录进行比较

c)使用HQL(EJBQL)面向对象的查询语言(建议)

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. @Test  
  2. public void testUpdate7() {     
  3.     Session session =sessionFactory.getCurrentSession();  
  4.     session.beginTransaction();  
  5.     Query q =session.createQuery("updateStudent s sets.name='z5' where s.id = 1");  
  6.     q.executeUpdate();  
  7.     session.getTransaction().commit();      
  8. }   

saveOrUpdate()

在执行的时候hibernate会检查,如果对象在数据库中已经有对应的记录(是指主键),则会更新update,否则会添加数据save

clear()

清除session缓存

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

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. Session session=sessionFactory.getCurrentSession();  
  2. session.beginTransaction();  
  3. Teacher t =(Teacher)session.load(Teacher.class,1);  
  4. System.out.println(t.getName());        
  5. session.clear();        
  6. Teacher t2=(Teacher)session.load(Teacher.class1);  
  7. System.out.println(t2.getName());  
  8. session.getTransaction().commit();  

注意:这样就会发出两条SELECT语句,如果把session.clear()去除,则只会发出一条SELECT语句,因为第二次load时,是使用session缓存中ID为1的对象,而这个对象已经在第一次load到缓存中了。

flush()

在hibernate中也存在flush这个功能,在默认的情况下session.commit()之前时,其实执行了一个flush命令。

Session.flush功能:

清理缓存;

执行sql(确定是执行SQL语句(确定生成update、insert、delete语句等),然后执行SQL语句。)

Session在什么情况下执行flush:

①默认在事务提交时执行;

注意:flush时,可以自己设定,使用session.setFlushMode(FlushMode)来指定。

  session.setFlushMode(FlushMode);

FlushMode的枚举值:

l     FlushMode.ALWAYS:任务一条SQL语句,都会flush一次

l     FlushMode.AUTO  :自动flush(默认)

l     FlushMode.COMMIT: 只有在commit时才flush

l     FlushMode.MANUAL:手动flush。

l    FlushMode.NEVER :永远不flush  此选项在性能优化时可能用,比如session取数据为只读时用,这样就不需要与数据库同步了

注意:设置flush模式时,需要在session开启事务之前设置。

②可以显式的调用flush;

③在执行查询前,如:iterate.

注:如果主键生成策略是uuid等不是由数据库生成的,则session.save()时并不会发出SQL语句,只有flush时才会发出SQL语句,但如果主键生成策略是native由数据库生成的,则session.save的同时就发出SQL语句。

evict()

例如:session.evict(user)

作用:从session缓存(EntityEntries属性)中逐出该对象

但是与commit同时使用,会抛出异常

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. session =HibernateUtils.getSession();  
  2. tx =session.beginTransaction();  
  3.     
  4. User1 user = newUser1();  
  5. user.setName("李四");  
  6. user.setPassword("123");  
  7. user.setCreateTime(newDate());  
  8. user.setExpireTime(newDate());  
  9.             
  10. //利用Hibernate将实体类对象保存到数据库中,因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理,不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false  
  11. session.save(user);  
  12.                 
  13. session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象  
  14. //无法成功提交,因为hibernate在清理缓存时,在session的临时集合(insertions)中取出user对象进行insert操作后需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session中逐出了,所以找不到相关数据,无法更新,抛出异常。  
  15.             
  16. tx.commit();  
  17. 解决在逐出session缓存中的对象不抛出异常的方法:  
  18. 在session.evict()之前进行显示的调用session.flush()方法就可以了。  
  19. session.save(user);  
  20.                 
  21. //flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象清除,并且会设置session中的existsInDatabase状态为false  
  22. session.flush();  
  23.             
  24. session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象  
  25.             
  26. //可以成功提交,因为hibernate在清理缓存时,在Session的insertions中集合中无法找到user对象所以不会发出insert语句,也不会更新session中existsInDatabase的状态。  
  27. tx.commit();  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值