当前位置首页 > 高等教育 > 大学课件/教案
搜柄,搜必应! 快速导航 | 使用教程  [会员中心]

hibernate传智播客李勇

文档格式:PPT| 50 页|大小 623.50KB|积分 30|2024-09-21 发布|文档ID:243337102
第1页
下载文档到电脑,查找使用更方便 还剩页未读,继续阅读>>
1 / 50
此文档下载收益归作者所有 下载文档
  • 版权提示
  • 文本预览
  • 常见问题
  • 单击此处编辑母版标题样式,,单击此处编辑母版文本样式,,第二级,,第三级,,第四级,,第五级,,*,,*,,—高级软件人才实作培训专家!,Hibernate原理与应用,讲师:,1,,主要内容,引入,,安装配置,,基本概念和,CURD,,HQL,和,Criteria,,关联映射,,继承映射,,集合映射,,懒加载,,缓存,,事务,,其他,,Hibernate,不适合的场景,,与,JPA,的集成,(annotation,方式,),,最佳实践,2,,引入,模型不匹配,(,阻抗不匹配,),,Java,面向对象语言,对象模型,其主要概念有:继承、关联、多态等;数据库是关系模型,其主要概念有:表、主键、外键等解决办法,,,1,使用,JDBC,手工转换2,使用,ORM(Object Relation Mapping,对象关系映射,),框架来解决,主流的,ORM,框架有,Hibernate,、,TopLink,、,OJB,3,,安装配置,下载地址,http://,,本教程使用,3.2.5,将下载目录,/hibernate3.jar,和,/lib,下的,hibernate,运行时必须的包加入,classpath,中:,,,antlr.jar,cglib.jar,asm.jar,commons-collections.jar,commons-logging.jar,jta.jar,dom4j.jar,4,,安装配置,配置文件,hibernate.cfg.xml,和,hibernate.properties,,,XML,和,properties,两种,这两个文件的作用一样,提供一个即可,推荐,XML,格式,下载目录,/etc,下是示例配置文件。

    可以在配置文件指定:,,,数据库的,URL,、用户名、密码、,JDBC,驱动类、方言等启动时,Hibernate,会在,CLASSPATH,里找这个配置文件映射文件,(hbm.xml,,对象模型和关系模型的映射,),在,/eg,目录下有完整的,hibernate,示例快速开始小例子,5,,基本概念和CURD,开发流程,,1由Domain object -> mapping->db官方推荐),,2由DB开始,用工具生成mapping和Domain object使用较多),,3由映射文件开始6,,基本概念和CURD,Domain Object限制,,1.默认的构造方法(必须的)2有无意义的标示符id(主键)(可选),,3非final的,对懒加载有影响(可选),,Domain Java Object(User),,public,,class,User {,,private,,int,id;,,private,String name;,,private,Date birthDay;,,,,//getter setter…,,},7,,基本概念和CURD,1.hbm.xml,,,,,,,,,,,,,,,,,,,,,,主键生成器,参考文档P65 5.1.4,,2.详细信息见参考文档P62,,8,,基本概念和CURD,Java代码,,1.初始化代码(只做一次),,,Configuration cfg = new Configuration();,,cfg.configure(“config.cfg.xml”);,,也可以通过cfg.setProperty设置属性。

    SessionFactory sessionFactory = cfg.buildSessionFactory();,,2.模板代码,,Session session = null;Transaction tx = null;,,try{,,session = sessionFactory.openSession();,,tx = session.beginTransaction();,,//…你的代码save,delete,update,get…,,mit();,,}catch(Exception e){,,if(tx !=null)tx.rollback();throw e;,,}finally{,,if(session != null)session.close();,,},9,,基本概念和CURD,Session,的几个主要方法,,,1.save,persist,保存数据,,persist,在事务外不会产生,insert,语句2.delete,,删除对象,,,3.update,,更新对象,如果数据库中没有记录,会出现异常4.get,,根据,ID,查,会立刻访问数据库5.Load,,根据,ID,查,,(,返回的是代理,不会立即访问数据库,),。

    6.saveOrUpdate,merge(,根据,ID,和,version,的值来确定是,save,或,update),,调用,merge,你的对象还是托管的7.lock(,把对象变成持久对象,但不会同步对象的状态,),10,,对象状态,瞬时,(transient),:数据库中没有数据与之对应,超过作用域会被,JVM,垃圾回收器回收,一般是,new,出来且与,session,没有关联的对象持久,(persistent),:数据库中有数据与之对应,当前与,session,有关联,并且相关联的,session,没有关闭,事务没有提交;,持久对象状态发生改变,在事务提交时会影响到数据库,(hibernate,能检测到,),脱管,(detached),:数据库中有数据与之对应,但当前没有,session,与之关联;托管对象状态发生改变,,hibernate,不能检测到11,,对象状态,12,,HQL和Criteria,HQL(Hibernate Query Language),,,面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了JAVA类和属性其他部分不区分大小写);HQL中查的是对象而不是和表,并且支持多态;HQL主要通过Query来操作,Query的创建方式:,,Query q = session.createQuery(hql);,,from Person,,from,User,,user,where,=:name,,from,User user,where,=:name and,user.birthday,,<,,:birthday,,Criteria,,,Criteria,是一种比,HQL,更面向对象的查询方式;,Criteria,的创建方式:,,,Criteria,crit,=,session.createCriteria(DomainClass.class,);,,,简单属性条件如:,criteria.add(Restrictions.eq(propertyName,, value)),,,,criteria.add(Restrictions.eqProperty(propertyName,otherPropertyName,)),,13,,基本功能练习,实现UserDao,,public interface UserDao {,,public void saveUser(User user);,,public User findUserById(int id);,,public User findUserByName(String name);,,public void updateUser(User user);,,public void remove(User user);,,},14,,基本功能练习,实验步骤:,,1.设计domain对象User。

    2.设计UserDao接口3.加入hibernate.jar和其依赖的包4.编写User.hbm.xml映射文件,可以基于hibernate/eg目录下的org/hibernate/auction/User.hbm.xml修改5.编写hibernate.cfg.xml配置文件,可以基于hibernate/etc/hibernate.cfg.xml修改;必须提供的几个参数:,,connection.driver_class、connection.urername、connection.password、dialect、hbm2ddl.auto6.编写HibernateUtils类,主要用来完成Hibnerate初始化和提供一个获得Session的方法;这步可选7.实现UserDao接口15,,关联映射,多对一,(Employee - Department),,一对多,(Department-Employee),,一对一,(room - door),,多对多,(teacher - student),,组件映射,(User-Name),,集合映射,(set, list, map, bag),,inverse,和,cascade(Employee,– Department),16,,关联映射,多对一(Employee - Department),,映射文件,,ER图,,17,,关联映射,一对多(Department-Employee),,,,,,,,,18,,关联映射,一对一(Person - IdCard),,1)基于主键的one-to-one(person的映射文件),,,,idCard,,,,,19,,关联映射,一对一(Person - IdCard),,2)基于外健的one-to-one,可以描述为多对一,加unique=“true”约束,,,,property-ref用于指定关联类的一个属性,这个属性将会和本外键相对应,,,,,,,,20,,关联映射,多对多(teacher - student),,在操作和性能方面都不太理想,所以多对多的映射使用较少,实际使用中最好转换成一对多的对象模型;Hibernate会为我们创建中间关联表,转换成两个一对多。

    21,,关联映射,组件映射(User-Name),,关联的属性是个复杂类型的持久化类,但不是实体即:数据库中没有表与该属性对应,但该类的属性要之久保存的当组件的属性不能和表中的字段简单对应的时候可以选择实现:,,ertype. UserType或,,ertype. CompositeUserType,22,,继承映射,对象模型(Java类结构),,23,,继承映射,一个类继承体系一张表(subclass)(表结构),24,,继承映射,一个类继承体系一张表(subclass)(映射文件),,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,继承映射,每个子类一张表(joined-subclass) (表结构),26,,继承映射,每个子类一张表(joined-subclass) (映射文件),,,,,,,,,,,,,,,,,,,,,,,,,,,,,27,,继承映射,混合使用“一个类继承体系一张表”和“每个子类一张表” (表结构),28,,继承映射,混合使用“一个类继承体系一张表”和“每个子类一张表” (映射文件),,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,29,,继承映射,每个具体类一张表(union-subclass) (表结构),30,,继承映射,每个具体类一张表(union-subclass) (映射文件),,,,,,,,,,,,,,,,,,,,,,,,,,主健不能是identity类型,如果父类是abstract=”true”就不会有表与之对应。

    隐式多态,映射文件没有联系,限制比较多很少使用31,,集合映射,集合映射(set, list, array,bag, map),,,,,,,, -->,,,,,32,,集合映射,集合映射(set, list, array,bag, map),,,,,,

    集合的简单使用原则:,大部分情况下用,set,,需要保证集合中的顺序用,list,,想用,java.util.List,又不需要保证顺序用,bag,35,,集合映射,cascade和inverse,,(Employee – Department),,Casade,用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似的操作,常用的,cascade:,,none,all,save-update ,delete, lock,refresh,evict,replicate,persist,,,merge,delete-orphan(one-to-many),一般对,many-to-one,many-to-many,不设置级联,在,,和,,中设置级联inverse,表“,是否放弃维护关联关系,”,(,在,Java,里两个对象产生关联时,对数据库表的影响,),,在,one-to-many,和,many-to-many,的集合定义中使用,,inverse=”true”,表示该对象不维护关联关系;该属性的值一般在使用有序集合时设置成,false,(注意,hibernate,的缺省值是,false,)。

    one-to-many,维护关联关系就是更新外键many-to-many,维护关联关系就是在中间表增减记录注,:,配置成,one-to-one,的对象不维护关联关系,,36,,懒加载,通过asm和cglib二个包实现;Domain是非final的1.session.load懒加载2.one-to-one(元素)懒加载:,,必需同时满足下面三个条件时才能实现懒加载,,(主表不能有constrained=true,所以主表没有懒加载),,lazy!=false 2)constrained=true 3)fetch=select,,3.one-to-many (元素)懒加载:1)lazy!=false 2)fetch=select,,4.many-to-one (元素) :1)lazy!=false 2)fetch=select,,5.many-to-many (元素) :1)lazy!=false 2)fetch=select,,6.能够懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId和getClass除外)hibernate会初始化这些代理,或用Hibernate.initialize(proxy)来初始化代理对象;当相关联的session关闭后,再访问懒加载的对象将出现异常。

    37,,缓存,缓存的作用主要用来提高性能,可以简单的理解成一个Map;使用缓存涉及到三个操作:把数据放入缓存、从缓存中获取数据、删除缓存中的无效数据一级缓存,Session级共享save,update,saveOrUpdate,load,get,list,iterate,lock这些方法都会将对象放在一级缓存中,一级缓存不能控制缓存的数量,所以要注意大批量操作数据时可能造成内存溢出;可以用evict,clear方法清除缓存中的内容38,,缓存,二级缓存,SessionFactory级共享实现为可插拔,通过修改,cache.provider_class,参数来改变,;,,hibernate,内置了对,EhCache,OSCache,TreeCache,SwarmCache,的支持,可以通过实现,CacheProvider,和,Cache,接口来加入,Hibernate,不支持的缓存实现在,hibernate.cfg.xml,中加入,:,,,,,或在映射文件的,class,元素加入子元素,:,,,,,其中,usage:read-only,read-write,nonstrict-read-write,transactional,,Session,的,:save(,这个方法不适合,native,生成方式的主键,),,,,update,saveOrUpdate,list,iterator,get,load,,,以及,Query,Criteria,都会填充二级缓存,但只有,(,没打开查询缓存时,)Session,的,iterator,get,load,会从二级缓存中取数据,(,iterator,可能存在,N+1,次查询,),。

    Query,Criteria,(,查询缓存,),由于命中率较低,所以,hibernate,缺省是关闭;修改,e_query_cache,为,true,打开对查询的缓存,并且调用,query.setCacheable(true,),或,criteria.setCacheable(true,),SessionFactory,中提供了,evictXXX,(),方法用来清除缓存中的内容统计信息打开,generate_statistics,,用,sessionFactory.getSatistics,(),获取统计信息39,,缓存,分布式缓存和中央缓存使用缓存的条件,,1.,读取大于修改2.,数据量不能超过内存容量3.,对数据要有独享的控制4.,可以容忍出现无效数据40,,事务,JDBCTransaction,,,单个数据库(一个SesisonFactory对应一个数据库),由JDBC实现Session session = null;,,Transaction tx =null;,,try {,,session = sessionFactory.openSession();,,tx = session.beginTransaction();,,//process,,mit();,,} catch(HibernateException e){,,if(tx != null)tx.rollback();throw e;,,}finally {,,if (session != null)session.close();,,},,connection.setAutoCommit(false);,,mit();conn.rollback();,41,,事务,JTATransaction,,可以简单的理解成跨数据库的事物,由应用JTA 容器实现;使用JTATransaction需要配置hibernate.transaction.factory_class参数,该参数缺省值是org.hibernate.transaction. JDBCTransactionFactory,当使用JTATransaction时需要将该参数改成org.hibernate.transaction.JTATransactionFactory,并配置erTransaction参数JNDI名(Hibernate在启动JTATransaction时要用该值到JNDI的上下文Context中去找erTransaction)。

    erTransactin tx = context.lookup(“jndiName”);,,try{,,tx.begin();,,//多个数据库的session操作;,,//session1….,,//session2….,,mit();,,}catch(Exception e){,,tx.rollback(); throw e;,,},42,,事务,session context,和事务边界,,用,current_session_context_class,属性来定义,context,(用,sessionFactory.getCurrentSession,(),来获得,session,),其值为:,,1.thread,:,ThreadLocal,来管理,Session,实现多个操作共享一个,Session,,避免反复获取,Session,,并控制事务边界,此时,session,不能调用,close,当,commit,或,rollback,的时候,session,会自动关闭,(,connection.release_mode:after_transaction,),Open session in view,:在生成(渲染)页面时保持,session,打开。

    2.jta,:由,JTA,事务管理器来管理事务,(,connection.release_mode:after_statement,),悲观锁和乐观锁,,悲观锁由数据库来实现;乐观锁,hibernate,用,version,和,timestamp,来实现,43,,其他问题,hibernate.cfg.xml,和,hbm.xml,内容解释,,数据类型,,,,1.,,type,可以是,hibernate,、,java,类型或者你自己的类型,(,需要实现,hibernate,的一个接口,),2.,基本类型一般不需要在映射文件,(,hbm.xml,),中说明,只有在一个,JAVA,类型和多个数据库数据类型相对应时并且你想要的和,hibernate,缺省映射不一致时,需要在映射文件中指明类型,(,如,:,java.util.Date,,,数据库,DATE,TIME,DATATIME,TIMESTAMP,,,hibernate,缺省会把,java.util.Date,映射成,DATATIME,型,而如果你想映射成,TIME,,则你必须在映射文件中指定类型,),3.,数据类型的对应关系见参考文档,5.2.2,,Session,是非线程安全的,生命周期较短,代表一个和数据库的连接,在,B/S,系统中一般不会超过一个请求;内部维护一级缓存和数据库连接,如果,session,长时间打开,会长时间占用内存和数据库连接。

    SessionFactory,是线程安全的,一个数据库对应一个,SessionFactory,,生命周期长,一般在整个系统生命周期内有效;,SessionFactory,保存着和数据库连接的相关信息(,user,,,password,,,url,)和映射信息,以及,Hibernate,运行时要用到的一些信息44,,其他问题,flush,时将一级缓存与数据库同步,,大批处理,,大量操作数据时可能造成内存溢出,解决办法如下:,,,1.,清除,session,中的数据,,,for(int,i=0;i<100000;i++)session.save(obj);,,,for(int,i=0;i<100000;i++){,,,session.save(obj,);,,,if(i,% 50 == 0){session.flush();,session.clear,();},,},,2.,用,StatelessSession,接口:它不和一级缓存、二级缓存交互,也不触发任何事件、监听器、拦截器,通过该接口的操作会立刻发送给数据库,与,JDBC,的功能一样StatelessSession,s =,sessionFactory.openStatelessSession,();,该接口的方法与,Session,类似。

    3.Query.executeUpdate(),执行批量更新,会清除相关联的类二级缓存,(,sessionFactory.evict(class,)),,也可能会造成级联,和乐观锁定出现问题,,45,,其他问题,HQL,,1,查询多个对象,select art, user from Article art, User,user,where,art.author.id,=,user.id,and,art.id,=:id,这种方式返回的是,Object[],,,Object[0]:article,Object[1]:user,2,分页,query.setFirstResult,query.setMaxResults,.,,,查询记录总数,query.iterate(“select,count(*) from,Person”).next,(),,,3,批量更新,query.executeUpdate,(),可能造成二级缓存有实效数据Criteria,,1,排序,Criteria.addOrder(Order.desc(propertyName,));,,,2,关联查询,criteria.setFetchMode(“propertyName,”,,FetchMode.SELECT,),与映射文件中关联关系的,fetch,作用一致。

    3,投影,Projections.rowCount(),max(propertyName,),,avg,,,groupProperty,…,,,4,分页,Projections.rowCount(),criteria.setFirstResult(),criteria.setMaxResults,(),,5DetachedCriteria,可在,session,外创建(在其他层创建比如在,Service,中创建)然后用,getExecutableCriteria(session,),方法创建,Criteria,对象来完成查询6Example,查询,,,Example.create(obj);criteria.add(example,),46,,其他问题,N+1,次查询和懒加载,,,1.,用,Query.iterator,可能会有,N+1,次查询2.,懒加载时获取关联对象3.,如果打开对查询的缓存即使用,list,也可能有,N+1,次查询拦截器与事件,,拦截器与事件都是,hibernate,的扩展机制,,Interceptor,接口是老的实现机制,现在改成事件监听机制;他们都是,hibernate,的回调接口,,hibernate,在,save,delete,update,…,等会回调这些类。

    SQL,和命名查询,,用,Map,代替,Domain,对象;将对象转化为,XML,47,,Hibernate不适合的场景,不适合,OLAP(On,-Line Analytical Processing,联机分析处理,),,以查询分析数据为主的系统;适合,OLTP,(,on-line transaction processing,联机事务处理)对于些关系模型设计不合理的老系统,也不能发挥,hibernate,优势数据量巨大,性能要求苛刻的系统,,hibernate,也很难达到要求,,,批量操作数据的效率也不高48,,与JPA的集成(annotation方式),需要添加的包,ejb3-persistence.jar, hibernate-,entitymanager.jar,, hibernate-,annotations.jar,, hibernate-commons-,annotations.jar,,,jboss-archive-browsing.jar,,,javassist.jar,,,配置文件,%CLASSPATH%/META-INF/,persistence.xml,,JAVA,代码:,,,EntityManagerFactory,,emf,=,Persistence.createEntityManagerFactory(name,);,,//(Name:,在,persistence.xml,中指定。

    ),,,EntityManager,,em,=,emf.createEntityManager,();,,,EntityTransaction,,tx,=,em.getTransaction,();,,,Tx.begin,();,,,Em.persist(entity);//remove,merge,find,,,Tmit,();,,,Em.close,();,,,Emf.close,();,49,,最佳实践,见,hibernate,参考文档,50,,。

    点击阅读更多内容
    卖家[上传人]:hylsxwd
    资质:实名认证