已阅读5页,还剩114页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Hibernate关系映射,在面向对象设计和实体模型关系中,对象间关系一般包括4种:一对一(one-to-one)、一对多(one-to-many)、多对一(many-to-one)、多对多(many-to-many)对象是现实世界中具有唯一性的事物一对一关联类型:主键关联与唯一外键关联一对一的主键关联形式是两张关联表通过主键形成一对一映射关系唯一外键关联是两张表的主键值不同,使用一个新添加的字段来作为外键维持一对一关系单向一对多只需在“一”的一方进行配置,反之就是单向多对一双向一对多就是对单向一对多的一种改进,4.3Hibernate关系映射,4.3.1一对一关联1.共享主键方式在注册某个论坛会员的时候,往往不但要填写登录账号和密码,还要填写其他的详细信息,这两部分信息通常会放在不同的表中,如表4.1、表4.2所示。,表4.1登录表Login,表4.2详细信息表Detail,4.3.1一对一关联,登录表和详细信息表属于典型的一对一关联关系,可按共享主键方式进行。步骤如下:创建Java项目,命名为“Hibernate_mapping”。添加Hibernate开发能力,步骤同4.2.1节第4步。HibernateSessionFactory类同样位于org.util包下。编写生成数据库表对应的Java类对象和映射文件。Login表对应的POJO类Login.java:,packageorg.model;publicclassLoginimplementsjava.io.Serializableprivateintid;/ID号privateStringusername;/登录账号privateStringpassword;/密码privateDetaildetail;/详细信息/省略上述各属性的getter和setter方法,4.3.1一对一关联,Detail表对应的Detail.java:,packageorg.model;publicclassDetailimplementsjava.io.Serializableprivateintid;/ID号privateStringtrueName;/真实姓名privateStringemail;/电子邮件privateLoginlogin;/登录信息/省略上述各属性的getter和setter方法,4.3.1一对一关联,Login表与Login类的ORM映射文件Login.hbm.xml。,detail,4.3.1一对一关联,Detail表与Detail类的ORM映射文件Detail.hbm.xml:,name表示属性名字,class表示被关联的类的名字cascade=“all”表明主控类的所有操作,对关联类也执行同样操作lazy=false表示此关联为立即加载,4.3.1一对一关联,在hibernate.cfg.xml文件中加入配置映射文件的语句。创建测试类。在src文件夹下创建包test,在该包下建立测试类“Test.java”。,Sessionsession=HibernateSessionFactory.getSession();Transactionts=session.beginTransaction();/创建事务对象Detaildetail=newDetail();Loginlogin=newLogin();login.setUsername(yanhong);login.setPassword(123);detail.setTrueName(严红);detail.setEmail(yanhong);/相互设置关联login.setDetail(detail);detail.setLogin(login);/这样完成后就可以通过Session对象调用session.save(detail)来持久化该对象session.save(detail);mit();HibernateSessionFactory.closeSession();,4.3.1一对一关联,运行程序,测试结果。因为该程序为JavaApplication,所以可以直接运行。在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,Login表和Detail表的内容如图4.12、图4.13所示。,图4.12Login表图4.13Detail表,4.3.1一对一关联,2.唯一外键方式唯一外键的情况很多,例如,每个人对应一个房间。其实在很多情况下,可以是几个人住在同一个房间里面,就是多对一的关系。但是如果把这个多变成唯一,也就是说让一个人住一个房间,就变成了一对一的关系了,这就是前面说的一对一的关系其实是多对一关联关系的一种特殊情况。对应的Person表和Room表如表4.3、表4.4所示。,表4.3Person表,表4.4Room表,4.3.1一对一关联,步骤如下:在项目Hibernate_mapping的org.model包下编写生成数据库表对应的Java类对象和映射文件。,Person表对应的POJO类Person.java:packageorg.model;publicclassPersonimplementsjava.io.SerializableprivateIntegerid;privateStringname;privateRoomroom;/省略上述各属性的getter和setter方法Room表对应的POJO类Room.java:packageorg.model;publicclassRoomimplementsjava.io.Serializableprivateintid;privateStringaddress;privatePersonperson;/省略上述各属性的getter和setter方法,4.3.1一对一关联,Person表与Person类的ORM映射文件Person.hbm.xml:,/唯一性约束,实现一对一,4.3.1一对一关联,Room表与Room类的ORM映射文件Room.hbm.xml:,/指定关联类的属性名,4.3.1一对一关联,在hibernate.cfg.xml文件中加入如下的配置映射文件的语句。编写测试代码。在src文件夹下的包test的Test类中加入如下代码:,Personperson=newPerson();person.setName(liumin);Roomroom=newRoom();room.setAddress(NJ-S1-328);person.setRoom(room);session.save(person);,4.3.1一对一关联,运行程序,测试结果。因为该程序为JavaApplication,所以可以直接运行。在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,Person表和Room表的内容如图4.14、图4.15所示。,图4.14Person表图4.15Room表,4.3.2多对一单向关联,只要把上例中的一对一的唯一外键关联实例稍微修改就可以变成多对一。步骤如下:在项目Hibernate_mapping的org.model包下编写生成数据库表对应的Java类对象和映射文件。其对应表不变,Person表对应的类也不变,对应的Person.hbm.xml文件修改如下:,/主控类所有操作,对关联类也执行同样操作,4.3.2多对一单向关联,而Room表不变,对应的POJO类如下:Room表与Room类的ORM映射文件Room.hbm.xml如下:,packageorg.model;publicclassRoomimplementsjava.io.Serializableprivateintid;privateStringaddress;/省略上述各属性的getter和setter方法,4.3.2多对一单向关联,编写测试代码。在src文件夹下的包test的Test类中加入如下代码:,Roomroom=newRoom();room.setAddress(NJ-S1-328);Personperson=newPerson();person.setName(liuyanmin);person.setRoom(room);session.save(person);,4.3.2多对一单向关联,运行程序,测试结果。因为该程序为JavaApplication,所以可以直接运行。在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,Person表和Room表的内容如图4.16、图4.17所示。,图4.16Person表图4.17Room表,4.3.3一对多双向关联,下面通过修改4.3.2节的例子来完成双向多对一的实现。步骤如下:在项目Hibernate_mapping的org.model包下编写生成数据库表对应的Java类对象和映射文件。Person表对应的POJO及其映射文件不用改变,现在来修改Room表对应的POJO类及其映射文件。对应的POJO:,packageorg.model;importjava.util.HashSet;importjava.util.Set;publicclassRoomprivateintid;privateStringaddress;privateSetperson=newHashSet();/集合,存放多个Person对象/省略getter和setter方法,4.3.3一对多双向关联,下面通过修改4.3.2节的例子来完成双向多对一的实现。步骤如下:在项目Hibernate_mapping的org.model包下编写生成数据库表对应的Java类对象和映射文件。Room表与Room类的ORM映射文件Room.hbm.xml。,/级联程度/充当外键的字段名/被关联的类名字,表示关联关系的维护工作由谁来负责,默认false,表示由主控方负责;true表示由被控方负责。由于该例是双向操作,故需要设为false,也可不写,22,inverse,只有集合标记(set/map/list/array/bag)才有inverse属性在Hibernate中,inverse指定了关联关系的方向。关联关系中inverse=false的为主动方,由主动方负责维护关联关系在没有设置inverse=true的情况下,父子两边都维护父子关系在1-N关系中,将many方设为主控方(inverse=false)将有助于性能改善(如果要国家元首记住全国人民的名字,不是太可能,但要让全国人民知道国家元首,就容易的多)在1-N关系中,若将1方设为主控方会额外多出update语句。插入数据时无法同时插入外键列,因而无法为外键列添加非空约束,4.3.3一对多双向关联,下面通过修改4.3.2节的例子来完成双向多对一的实现。步骤如下:在项目Hibernate_mapping的org.model包下编写生成数据库表对应的Java类对象和映射文件。该配置文件中cascade配置的是级联程度,它有以下几种取值:,all:表示所有操作句在关联层级上进行连锁操作。save-update:表示只有save和update操作进行连锁操作。delete:表示只有delete操作进行连锁操作。all-delete-orphan:在删除当前持久化对象时,它相当于delete;在保存或更新当前持久化对象时,它相当于save-update。另外它还可以删除与当前持久化对象断开关联关系的其他持久化对象。,4.3.3一对多双向关联,编写测试代码。在src文件夹下的包test的Test类中加入如下代码:,Personperson1=newPerson();Personperson2=newPerson();Roomroom=newRoom();room.setAddress(NJ-S1-328);person1.setName(李方方);person2.setName(王艳);person1.setRoom(room);person2.setRoom(room);/这样完成后就可以通过Session对象/调用session.save(person1)和session.save(person)/会自动保存roomsession.save(person1);session.save(person2);,4.3.3一对多双向关联,运行程序,测试结果。因为该程序为JavaApplication,所以可以直接运行。在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,Person表和Room表的内容如图4.18、图4.19所示。,图4.18Person表图4.19Room表,4.3.3一对多双向关联,由于是双向的,当然也可以从Room的一方来保存Person,在Test.java中加入如下代码:,.Personperson1=newPerson();Personperson2=newPerson();Roomroom=newRoom();person1.setName(李方方);person2.setName(王艳);Setpersons=newHashSet();persons.add(person1);persons.add(person2);room.setAddress(NJ-S1-328);room.setPerson(persons);/这样完成后,就可以通过Session对象/调用session.save(room)/会自动保存person1和person2.,4.3.3一对多双向关联,运行程序,插入数据后,Person表和Room表的内容如图4.20、图4.21所示。,图4.20Person表图4.21Room表,4.3.4多对多关联,1.多对多单向关联学生和课程就是多对多的关系,一个学生可以选择多门课程,而一门课程又可以被多个学生选择。多对多关系在关系数据库中不能直接实现,还必须依赖一张连接表。如表4.6、表4.7和表4.8所示。,表4.6学生表student,表4.7课程表course,表4.8连接表stu_cour,4.3.4多对多关联,由于是单向的,也就是说从一方可以知道另一方,反之不行。这里以从学生知道选择了哪些课程为例实现多对多单向关联。步骤如下:在项目Hibernate_mapping的org.model包下编写生成数据库表对应的Java类对象和映射文件。student表对应的POJO类如下:,packageorg.model;importjava.util.HashSet;importjava.util.Set;publicclassStudentimplementsjava.io.Serializableprivateintid;privateStringsnumber;privateStringsname;privateintsage;privateSetcourses=newHashSet();/省略上述各属性的getter和setter方法student表与Student类的ORM映射文件Student.hbm.xml。,4.3.4多对多关联,course表对应的POJO如下:,packageorg.model;publicclassCourseimplementsjava.io.Serializableprivateintid;privateStringcnumber;privateStringcname;/省略上述各属性的getter和setter方法。,4.3.4多对多关联,course表与Course类的ORM映射文件Course.hbm.xml在hibernate.cfg.xml文件中加入如下的配置映射文件的语句。,4.3.4多对多关联,编写测试代码。在src文件夹下的包test的Test类中加入如下代码。,Coursecour1=newCourse();Coursecour2=newCourse();Coursecour3=newCourse();cour1.setCnumber(101);cour1.setCname(计算机基础);cour2.setCnumber(102);cour2.setCname(数据库原理);cour3.setCnumber(103);cour3.setCname(计算机原理);Setcourses=newHashSet();courses.add(cour1);courses.add(cour2);courses.add(cour3);Studentstu=newStudent();stu.setSnumber(081101);stu.setSname(李方方);stu.setSage(21);stu.setCourses(courses);session.save(stu);/设置完成后就可以通过Session对象调用session.save(stu)完成持久化,4.3.4多对多关联,运行程序,测试结果。因为该程序为JavaApplication,所以可以直接运行。在完全没有操作数据库的情况下,程序就完成了对数据的插入。插入数据后,student表、course表及连接表stu_cour表的内容如图4.22、图4.23、图4.24所示。,图4.22student表,图4.23course表图4.24stu_cour表,4.3.4多对多关联,2.多对多双向关联首先将其Course表所对应的POJO对象修改成如下代码:,packageorg.model;importjava.util.HashSet;importjava.util.Set;publicclassCourseimplementsjava.io.Serializableprivateintid;privateStringcnumber;privateStringcname;privateSetstus=newHashSet();/省略上述各属性的getter和setter方法,4.3.4多对多关联,2.多对多双向关联Course表与Course类的ORM映射文件Course.hbm.xml:,/指定参照course表的外键名称/指定参照student表的外键名称,36,Hibernate关联映射小结,多对一(一对多)单向关联:只需在“多”或“一”进行配置,双向一对多需要在“一”和“多”都进行配置,37,级联:通常用在一对多和一对一关联中,主动方对象执行操作时,被关联对象(被动方)是否同步执行同一操作。,38,inverse=true”控制反转,在一对多双向关联的情况下,“多”方作为作为主主动方比一方在应用的执行效率高。在Hibernate中的一对多的单向或者双向关联的情况下,我们可以将“一”方控制权交给“多”方称为控制反转(inverse)。,39,延迟加载,Hibernate为了避免在关联查询中带来的无谓的性能开销,使用了延迟加载技术,仅在需要读取数据时才查询数据库例如:在Category和product的一对多关联查询中查询一个Category对象,同时读取其关联的多个product对象,则自动加载关联数据非常方便,如果仅需要获得Category对象的name属性值,而不关心其关联的product对象的属性值,则自动加载product对象的属性会导致无谓的系统开销。Session对象的load方法可以利用持久化对象的延迟加载,而get方法则不可。,40,Hibernate提供三种形式的延迟加载:持久化对象、集合对象和属性的延迟加载。如果一个数据库表中有一些大数据对象类型的字段,则加载该表对应的持久化对象必须每次都加载这些字段,而忽略其是否有用,从而带来大的性能开销。可以在需要使用这些字段对应的属性值时才在数据库中查询。可以通过在property标签的lazy属性设置为true来激活属性的延迟加载。,41,持久化对象的延迟加载,42,publicclassHibernateTest/ehcachecacheforcollectionpublicvoidtestLazyLoading01()Sessionsession=HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();Transactiontx=session.beginTransaction();Categorycategory=(Category)session.load(Category.class,newInteger(1);/System.out.println(category.getName();mit();运行后查看hibernate输出的SQL语句会发现hibernate没有输出任何的SQL语句,未真正查询数据库,因为load方法使用了持久对象的延迟加载,只有需要读取持久对象的属性时才会向数据库发出查询请求。Load方法返回的不是真正的持久化对象,是其中的一个代理对象。,43,集合对象的延迟加载,对于集合属性,通常推荐使用延迟加载策略。所谓延迟加载就是当系统需要使用集合属性时才从数据库装载关联的数据。Hibernate对集合属性默认采用延迟加载,在某些特殊的情况下为set,list,map等元素设置lazy=“false”属性来取消延迟加载。,44,集合对象的延迟加载,45,OSIV模式,为了更好的提高Hibernate的性能,Hibernate采用缓冲机制和延迟加载-关联的对象如果当时没必要就稍后加载。从而提高Hibernate的应用性能。但是在Web中分层模式可能会因Session的关闭导致抛出org.hibernate.LazyInitializationException;解决方案有2种:1、关闭延迟加载。不推荐使用2、延长Session对象的生命周期。这种方案比较好的。,46,首先写一个过滤器类,让这个类实现javax.servlet.Filter接口privateTransactiontx;privateSessionFactorysessionFactory;Overridepublicvoiddestroy()/TODOAuto-generatedmethodstubsessionFactory.close();OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException/TODOAuto-generatedmethodstubtrySessionsession=HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();tx=session.beginTransaction();chain.doFilter(request,response);mit();catch(Exceptione)/TODO:handleexceptionSystem.out.println(e.getStackTrace();tx.rollback();Overridepublicvoidinit(FilterConfigarg0)throwsServletException/TODOAuto-generatedmethodstubsessionFactory=HibernateSessionFactoryUtil.getSessionFactory();,47,继承映射,Hibernate的继承映射可以理解持久化类之间的继承关系。例如:人和学生之间的关系。学生继承了人,可以认为学生是一个特殊的人,如果对人进行查询,学生的实例也将被得到。,48,采用subclass元素的继承映射,在这种映射策略下,整个继承树的所有实例都保存在同一个表内。因为父类和子类的实例全部保存在同一个表中,因此需要在该表内增加一列,使用该列来区分每行记录是哪个类的实例-这个列被称为辨别者列(discriminator).在这种映射策略下,使用subclass来映射子类,使用discriminator-value指定辨别者列的值,49,采用subclass元素的继承映射,50,采用subclass元素的继承映射,生成的表及插入的数据person_table,注:所有子类定义的字段都不能有非空约束。如果为那些字段添加非空约束,那么父类的实例在那些列根本没有值,这将引起数据库完整性冲突,导致父类的实例无法保存到数据库中,51,采用joined-subclass元素的继承映射,采用这种映射策略时,父类实例保存在父类表中,子类实例由父类表和子类表共同存储。因为子类实例也是一个特殊的父类实例,因此必然也包含了父类实例的属性。于是将子类和父类共有的属性保存在父类表中,子类增加的属性,则保存在子类表中。在这种映射策略下,无须使用鉴别者列,但需要为每个子类使用key元素映射共有主键,该主键必须与父类标识属性的列名相同。但如果继承树的深度很深,可能查询一个子类实例时,需要跨越多个表,因为子类的数据一次保存在多个父类中。子类增加的属性可以添加非空约束。因为子类的属性和父类的属性没有保存在同一个表中采用joined-subclass元素的继承映射可以实现每个子类一张表,52,采用joined-subclass元素的继承映射,53,采用joined-subclass元素的继承映射,生成的表及插入的数据person_tablestudent_table,54,采用union-subclass元素的继承映射,采用union-subclass元素可以实现将每一个实体对象映射到一个独立的表中。union-subclass与joined-subclass映射策略类似:子类增加的属性也可以有非空约束-即父类实例的数据保存在父表中,而子类实例的数据保存在子类表中。与joined-subclass不同的是,子类实例的数据仅保存在子类表中,而在父类表中没有任何记录。在这种映射策略下,子类表的字段会比父类表的映射字段要多,因为子类表的字段等于父类表的字段加子类增加属性的总和在这种映射策略下,既不需要使用鉴别者列,也无须使用key元素来映射共有主键.,55,采用union-subclass元素的继承映射,56,采用union-subclass元素的继承映射,生成的表及插入的数据person_tablestudent_table,57,三种继承映射方式的比较,58,映射复合主键,复合主键:指有多个字段同时做为主键在Hibernate中,通过的子元素元素对复合主键进行定义(此元素和元素不能同时存在)对于复合主键而言,有两种映射方式:基于实体类属性的复合主键:复合主键由实体类中的某几个属性组成基于主键类的复合主键:复合主键由单独的主键类进行描述主键类必须实现java.io.Serializable接口主键类必须实现equals方法和hashcode方法以作为不同数据之间的标识,59,映射基于实体类属性的复合主键,以学生成绩表(STUDENT_GRADE)为例,主键为(STUDENT_ID+SUBJECT_ID)用映射文件配置如下:,60,映射基于主键类的复合主键,以学生成绩表(STUDENT_GRADE)为例,主键为(STUDENT_ID+SUBJECT_ID)为此创建独立的主键类StudentGradePK用映射文件配置如下:,61,Hibernate缓存深入详解,62,Hibernate缓存概述,Hibernate缓存机制对Hibernate的性能发挥一直处于一个极其重要的作用,它是持久层性能提升的关键。hibernate缓存在应用系统中的位置Hibernate缓存介于Hibernate应用和数据库之间,缓存中存放了数据库数据的拷贝。其作用是减少访问数据库的频率,从而提高应用的运行性能。Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做“缓存命中”),则就直接把命中的数据作为结果加以利用,避免的了建立数据库查询的性能损耗。,63,大纲,Hibernate缓存概述,1,Hibernate一级缓存(Session缓存),2,3,Hibernate二级缓存,4,查询缓存,64,Hibernate缓存分类,Hibernate提供了两级缓存:一级缓存:Session级别的缓存二级缓存:SessionFactory级别的全局缓存Hibernate的这两级缓存都位于持久化层,存放的都是数据库数据的拷贝。那么它们之间的区别是什么呢?为了理解二者的区别,需要深入理解持久化层的缓存的一个特性:缓存的范围。,65,缓存的范围,缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。,事务范围缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的的对象形式。一级缓存就属于事务范围。,66,缓存的范围(2),进程范围缓存被进程范围内的所有事务共享。这些事务有可能并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期,进程结束时,缓存也就结束了生命周期。它的物理介质可以是内存或硬盘。,67,缓存的范围(3),集群范围在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性,缓存中的数据通常采用对象的松散数据形式。持久化层的第二级缓存就存在于进程范围或集群范围。,68,Hibernate的缓存机制,Hibernate中提供了两级Cache.第一级别的缓存是Session级别的缓存,它是属于事务范围的缓存。随着session的关闭而消失,这一级别的缓存由hibernate管理的,一般情况下无需进行干预;第二级别的缓存是SessionFactory级别的缓存,它是属于进程范围或群集范围的缓存。这一级别的缓存可以进行配置和更改,并且可以动态加载和卸载。Hibernate还为查询结果提供了一个查询缓存,它依赖于第二级缓存。,69,缓存对getloadlistiterator的影响,session的load方法,会先从一级缓存中查询当前标识符属性(id)对应的数据,如果未命中缓存,再判断持久化对象是否配置了二级缓存,如果配置了再从二级缓存中查询,否则从数据库中查询数据并缓存到对应的一级和二级缓存。session的get方法,首先从一级缓存中查询,如果未命中,则直接从数据库中查询数据并缓存到相应的一级缓存中。Query对象的list方法,首先检查是否配置了查询缓存,如果配置,则判断是否能命中缓存,如果未命中,则直接从数据库中查询数据并缓存到相应的一级、二级和查询缓存中。Query对象iterator操作,首先从数据库中查询符合查询条件的标识符属性值,然后通过session的load方法查询当前标识符对应的数据。,70,理解一级缓存,(1)当应用程序调用Session接口的save()、update()、saveOrUpdate()时,如果Session缓存中还不存在相应的对象,Hibernate就会把该对象加入到第一级缓存中。(2)当调用Session接口的load()、get()以及Query查询接口的list()方法时,如果Session缓存中存在相应的对象,就不需要到数据库中检索。,71,Hibernate的一级缓存,Session为应用程序提供了两个管理缓存的方法:evict(Objectobj):从缓存中清除参数指定的持久化对象。clear():清空缓存中所有持久化对象。当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。,72,Session接口的用法,get()和load()试图从数据库加载一个实体对象时,Session先判断对象是否存在,如果存在就不到数据库中检索。返回的对象都位于Session缓存中,接下来修改了持久化对象的属性后,当Session清理缓存时,会根据持久化对象的属性变化来同步更新数据库。区别:(1)当数据库中不存在与OID对应的记录时,load()方法抛出ObjectNotFoundException异常,而get()方法返回null.(2)两者采用不同的检索策略。默认情况下,load()方法采用延迟检索策略(Hibernate不会执行select语句,仅返回实体类的代理类实例,占用内存很少);而get()采用立即检索策略(Hibernate会立即执行select语句)。使用场合:(1)如果加载一个对象的目的是为了访问它的各个属性,可以用get();(2)如果加载一个对象的目的是为了删除它,或者建立与别的对象的关联关系,可以用load();,73,Hibernate的一级缓存(2),举例说明:publicclassTestpublicvoidget()Sessionsession=HibernateSessionFactory.getSession();TUsert=(TUser)session.get(TUser.class,2);System.out.println(t.getName();session.close();进行测试:在控制台打印出一条SQL语句:Hibernate:selecttuser0_.idasid0_0_,tuser0_.nameasname0_0_fromtest.t_usertuser0_wheretuser0_.id=?说明进行了一次数据库的调用.,74,publicclassTestpublicvoidget()Sessionsession=HibernateSessionFactory.getSession();TUsert=(TUser)session.get(TUser.class,2);System.out.println(t.getName();TUsertt=(TUser)session.get(TUser.class,2);System.out.println(tt.getName();session.close();再进行测试:进行了两次查询,控制台仍然只打出一条SQL语句:Hibernate:selecttuser0_.idasid0_0_,tuser0_.nameasname0_0_fromtest.t_usertuser0_wheretuser0_.id=?说明还是只进行了一次数据库的调用,75,Hibernate的一级缓存(3),再将代码更改如下:publicclassTestpublicvoidget()Sessionsession=HibernateSessionFactory.getSession();TUsert=(TUser)session.get(hibernate.TUser,2);System.out.println(t.getName();session.close();Sessionsession1=HibernateSessionFactory.getSession();TUsertt=(TUser)session1.get(hibernate.TUser,2);System.out.println(tt.getName();session1.close();继续测试:进行两次查询控制台打印两条SQL语句:Hibernate:selecttuser0_.idasid0_0_,tuser0_.nameasname0_0_,tuser0_.sexassex0_0_fromtest.t_usertuser0_wheretuser0_.id=?Hibernate:selecttuser0_.idasid0_0_,tuser0_.nameasname0_0_,tuser0_.sexassex0_0_fromtest.t_usertuser0_wheretuser0_.id=?,76,Session清理缓存,清理缓存是指Session按照缓存中对象的属性变化来同步更新数据库。Session在清理缓存的时候会自动进行脏检查(dirty-check),如果发现Session缓存中的对象与数据库中相应的记录不一致,就会同步数据库。Session是如何进行脏检查的呢?当一个对象被加入到Session缓存时,Session会为该对象的值类型的属性复制一份快照。当Session清理缓存的时候,会进行脏检查,即比较对象的当前属性与它的快照,来判断对象的属性是否发生变化,如果发生变化,就称这个对象是“脏对象”,Session会根据脏对象的最新属性来执行相关的SQL语句,从而同步更新数据库。,77,Session何时清理缓存,session缓存中对象的属性每次发生变化,Session不会立即清理缓存及执行相关的update语句,而是在特定的时间点才清理缓存,这使得Session能够把几条相关的sql语句合并为一条sql语句,以便减少访问数据库的次数。以下代码对dept对象的deptName属性修改了两次:,Transactiontx=session.biginTransaction();Deptdept=(Dept)session.get(Dept.class,”001”);dept.setDeptName(“人事部”);dept.setDeptName(“人力资源部”);mit();,当Session清理缓存时,只会执行一条update语句,78,Session何时清理缓存,session会在下面的时间点清理缓存:(1)当应用程序调用org.hibernate.Transaction的commit()方法的时候commit()方法先清理缓存,然后再向数据库提交事务。(2)当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生变化,就会先清理缓存,使得Session缓存与数据库进行了同步,从而保证查询结果返回的是正确的数据。(3)当应用程序显式调用Session的flush()方法的时候,79,Sesion缓存的管理,第一级缓存在正常的情况下是由Hibernate自动维护的。在特殊的情况下需要我们进行手动维护,Hibernate就提供了两个管理Session缓存的方法:(1)Session.evict(Objecto)将某个特定的对象从缓存中清除,使用此方法有两种适用情形,一是在特定的操作(如批量处理),需要及时释放对象占用的内存。二是不希望当前Session继续运用此对象的状态变化来同步更新数据库。(2)Session.clear()清除缓存中的所有持久化对象。,1、在多数情况下并不提倡通过evit()和clear()来管理一级缓存。2、管理一级缓存最有效的方法是采用合理的检索策略和检索方式来节省内存的开销。,80,Hibernate两级缓存机制,Hibernate的两级缓存机制:如果在一级缓存中没有查询到相应的数据,可以到二级缓存中查找,如果在二级缓存中也没有找到数据,那么就只好查询数据库了。,81,CacheProviders(1),Hibernate本身并不提供二级缓存的产品化实现,而是为众多支持Hibernate的第三方缓存插件提供整和接口。通过在vider_class属性中指定org.hibernate.cache.CacheProvider的某个实现的类名,你可以选择让Hibernate使用哪个缓存实现。Hibernate打包一些开源缓存实现,提供对它们的内置支持。除此之外,你也可以实现你自己的缓存,将它们插入到系统中。,82,CacheProviders(2),Hibernate支持以下类型的缓存插件:为了把这些缓存插件集成到Hibernate中,Hibernate提供了org.hibernate.cache.CacheProvider接口,它是缓存插件和与Hibernate之间的适配器。Hibernate分别为这些缓存插件提供了内置的CacheProvider实现。,83,使用:org.hibernate.cache.EhCacheProvider来指定缓存提供商。即有谁来提供缓存的功能。Ehcache配置,84,Hibernate的二级缓存,Hibernate二级缓存是SessionFactory级的缓存,它允许多个Session间共享,使用时需要使用第三方的缓存组件,新版Hibernate将EHcache作为默认的二级缓存实现.,85,缓存的并发访问策略(1)cacheconcurrencystrategy,当两个并发的事务同时访问数据库相同数据的时候,有可能出现五类并发访问问题,因此必须采用必要的事务隔离措施。同样,两个并发的事务同时访问缓存的相同数据时,也有可能出现各类并发问题。因此必须为Hibernate二级缓存设定适当的并发访问策略,每一种策略对应一种事务隔离级别。,86,缓存的并发访问策略(2)cacheconcurrencystrategy,87,CacheConcurrencyStrategySupported,各种缓存插件对缓存并发访问策略的支持情况:,88,二级缓存的配置,配置二级缓存主要包含以下几个步骤:启用二级缓存;选择需要进行二级缓存的持久化类,设置它的缓存并发访问策略;选择合适的缓存插件;为命名缓存设置数据过期策略;,89,二级缓存的配置(1),启用二级缓存:在Hibernate的配置文件中配置属性注意:此属性对指定的类缺省为true。选择需要二级缓存的持久化类,设置它的缓存并发访问策略transactional|read-write|nonstrict-read-write|read-onlyHibernate允许在分散的各个映射文件中为持久化类设置二级缓存,也允许在Hibernate的配置文件中集中设置二级缓存,指定和元素,统一配置。后一种方式更有利于代码维护。,hibernate.cache.use_second_level_cache=true,90,二级缓存的配置(2),在映射文件中设置二级缓存.hbm.xml:类或者集合映射的“元素”的详细用法:,usage:(必须)说明了缓存的同步策略:transactional、read-write、nonstrict-read-write或read-only。region:(可选,默认为类或者集合的名字)指定二级缓存的区域名in
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 宜宾新高人才服务有限公司关于2026年招聘园区产业发展服务专员的(11人)考前冲刺试卷含答案详解【模拟题】
- 2026江西吉安市中医院面向社会招聘聘用制医师3人笔试题库附答案详解(研优卷)
- 2026辽宁材料实验室招聘高层次及急需紧缺人才6人(第一批)模拟试卷【考点梳理】附答案详解
- 2026广西防城港市医疗保障局招聘编外聘用人员1人笔试题库附答案详解(满分必刷)
- 2025年河南中原装备职业学院高职单招职业技能考试模拟试卷附答案详解【黄金题型】
- 统编版(2024)一年级下册吃水不忘挖井人第一课时教案
- 习作:身边那些有特点的人 教学设计统编版语文三年级下册
- 目标的过程管理与达成教学设计高中心理健康北师大版浙江专版高中三年级全一册-北师大版浙江专版
- 牛津译林版四年级下册Unit6Whosedressisthis教学设计
- 人教部编版五年级下册稚子弄冰教学设计
- 新生儿复苏操作技能考核评分标准(2025 版)中文版 逐项打分 + 合格判定细则
- 2025年广西卫生职业技术学院教职人员招聘笔试真题(含完整答案解析)
- 2026年医师定期考核试题题库中医入门试题及答案
- 山洪灾害预警识别知识
- 2026小红书有感运动IP方案
- 天然气管线保护施工方案
- 2025届中工国际工程股份有限公司校园招聘笔试历年参考题库附带答案详解
- 城市道路桥梁安全监测预警系统操作手册
- 2026计算机二级MS Office真题模拟押题含解析
- GB/Z 114.1-2026纳米制造技术规范纳米储能第1部分:空白详细规范电化学电容器用纳米多孔活性炭
- 消防培训机构设备管理制度
评论
0/150
提交评论