




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
宝宝 Hibernate学习总结Hibernate是一个开放源代码的ORM(对象关系映射)框架,它对JDBC进行了轻量级的封装,Java程序员可以使用面向对象的编程思维来操纵数据库,它通过对象属性和数据库表字段之间的映射关系,将对象持久化到数据库中,可以说Hibernate就是将数据从对象形式转换成表字段后存入数据库的一种框架。hibernate移植非常好,因为它用到了方言配置,可以根据不同的数据库自动发出不同的sql。下面是我感觉比较重要的方面就列出来了:首先是搭建环境:1、我建的是个Java项目,第一步先引入HIbernate的jar包:hibernate3.jar这是核心包,还有lib下的所有包。2、我用oracle做测试,所以在引入oracle的驱动包,classes12.jar。3、在从源码包中拷贝一个hibernate.cfg.xml(放到src下,而且这个文件的配置可以参考etc/perties这个文件)这是Hibernate的默认配置文件名字,和User.hbm.xml(此文件跟你的pojo放在一块)映射配置文件。这样Hibernate的环境基本上就搭建好了。4、hibernate可以根据映射文件和pojo自动创建数据库表(用SchemaExport这个类)。5、hibernate默认事务是手动的,所以我们必须手动获取事务,开启和关闭它。6、在hibernate中持久化对象有三个状态,这个面试时可能会问到:(1)transient瞬时态:在数据库中没有与之匹配的数据,一般就是只new出了这个对象,并且在session缓存中也没有即此对象没有纳入session的管理,此状态的对象不能直接存入数据库(会抛出TransientObjectException)。(2)persistent持久态:在数据库中有与之匹配的数据,并且纳入了session的管理(一般就是执行了save、update、load、get后的对象),在提交事务时(清理session缓存时)会和数据库同步更新,持久态对象才可以存入数据库。(3)detached游离态:在数据库中有与之匹配的数据,但没有纳入session缓存的管理。7、(1)讨论下hibernate的增(save)、删(delete)、改(update)、查(get,load)。增没什么说的,关于删除和修改时我们完全可以new出一个对象进行操作,只要给这个对象的标示赋值为库中存在的对象就行了,这个过程应该是这样的,当我们new出对象后并设置了相应的id(标示),然后执行session.delete()或者session.update()后,此对象在session缓存中就有了一份,再当我们commit提交事务时(清理缓存),数据库中有同样id标示的对象就会与session缓存中的持久态对象进行同步更新,所以这样更新和删除完全可以实现,但是我们一般不能这么,最好是先查出来在去更新或者删除,比如:当我们要更新一个User对象时,没有先查出来而是用new的方法并给这个新对象设置了一个与库中有对应ID的形式去更新,那么更新完后,如果没有赋值的属性都会变成null,这个可不是我们想要的结果哦。(2)在说说get和load这两个单一对象的查询方法:1 get方法不支持lazy延迟加载,即一执行到get方法立刻发出sql语句,而load有延迟加载,即load方法执行后,并不会执行查询sql只是返回了一个代理对象,只有等真正用到了这个对象才会发出查询语句。2当get方法查找的对象不存在则返回null,而load会抛出异常。共同点:load和get只能通过主键标示加载实体对象。8、数据库的隔离级别决定了只发出插入sql而没有提交事务后是否能select看到数据。其实只要发出了插入的sql语句,即使你没有提交事务,库里面就已经有了数据,只是数据库的默认隔离级别不会让你看到数据,这时你就可以回滚事务,取消数据插入,而且这种隔离级别还可以设置的。9、在hibernate中,持久态对象不能引用瞬时态对象。(插入有关联关系的对象时可能会遇到这种异常)。10、hiberntate级联(cascade)只对增、删、改有作用,与查询没关系,默认不会级联即值为none。11、在hibernate中对象之间的映射关系通常都配成双向的,比如双向一对一外键关联映射(这也是一对一中最常用的)。12、一对一主键关联默认就有级联关系,其他关联关系都没有这种默认设置。13、many-to-one标签会在当前表中加字段即外键,而one-to-one name=user标签不会加字段,指示hibernate如何加载关联对象,它默认就去另一张表中找主键与当前表主键相等的数据。14、在主键生成器中uuid和native比较常用,它们的区别是:(1)uuid在执行完save后只会把此对象放在session缓存中,并为其赋id值(是一个32位字符串),它只有事务提交时也就是清理了缓存时才会发出sql。(2)native在执行完save后就立刻发出插入sql语句,即此时库中已经有了此对象数据,而且native是根据本地数据库进行自增的,比如你用的是oracle,那它就会通过序列进行自增。15、hibernate中的flush方法可以清理session缓存并执行相应的sql,我们可以手动执行,但提交事务前也会被自动执行。16、hibernate中的双向多对一和一对多是同一个概念,而且一对多和多对一都是在多的一端加个外键来指向一的一端,一对多单向会发出多余的update语句(所以一般都配成双向)。17、hibernate一般在持久类中用到集合映射时都用Set(放入的对象不可重复)很少用List,而且还不能用Hashset具体类去声明,必须用接口Set去声明,因为hibernate对Set进行了扩展。18、hibernate映射文件的单双向都是针对加载而言的。19、hibernate支持lazy延迟加载(只有真正使用该对象时才会创建,即发出相应的sql语句),默认lazy都是true而且Session不能关,否则lazy就失效了,如果你在Session关闭后在把延迟加载的对象输出给页面就会抛出异常即特别是用load(它支持lazy)进行加载时Session关闭后在返回所查询的对象时就会抛此异常org.hibernate.LazyInitializationException,但用get()加载时就不存在这问题,因为lazy的生命周期和Session是同步的,这个面试可能会问到,解决方法就是不关Session,直到查询的内容已经返回给页面在关闭,Spring框架就提供了一个Filter(过滤器)实现了此功能即从请求访问一直到响应返回后在关闭Session。hibernate的延迟加载实现用的是第三方库cglib.jar,这是个动态代理类库,跟JDK的动态代理是不一样的,JDK的动态代理只能代理实现了一定的接口的类。hibernate的lazy可以应用的标签类型有class、property、one-to-one、many-to-one、集合。20、get和load两个方法在同一个session中都会用到session缓存(也就是hibernate一级缓存)在执行这两个方法后都会给session缓存中放一份,即第二次查询同一对象时不会在发出sql,只会从一级缓存中直接读取数据,一级缓存只缓存实体对象,不缓存普通属性,而且一级缓存的生命周期和Session的生命周期是一致的,不同的Session之间不能共享Session缓存中的数据。21、session.save()时也用到了一级缓存,即添加完后会给session缓存中放一份对象。22、一级缓存不能控制,包括设置容量、或者取消,只能通过session.clear()等方法清空它。一级缓存是session缓存即同一个session共享,二级缓存是进程级的缓存即SessionFactory级缓存(它的生命周期和SessionFactory一致),不同session之间是可以共享的,它们的共同点是都缓存对象,不缓存普通属性。Hibernate的二级缓存集成了第三方库,比如:ehcache,而且使用时必须配置(如:配置用哪种二级缓存,哪些实体类使用二级缓存)。二级缓存的简单示例:比如当二级缓存没配置时(默认是开启的)-我们用load或者get查询时先会去一级缓存中查,没有找到再发出SQL。当二级缓存开启并配置后-查询时先去一级缓存,如果没有在去二级缓存找,再没有就发出相应的SQL.。当二级缓存开启并配置后,load和get查询默认后会给一级缓存和二级缓存中都放一份(可以配置不往二级缓存中放),二级缓存可以被SessionFactory去直接管理,比如:清空。Hibernate还有一种缓存叫查询缓存(Hibernate默认是关闭的)此缓存对Query.iterate()不起作用,它是缓存普通属性和对象id标示的,它的生命周期不可控制(与session的生命周期没有关系的),利用率不高,此缓存使用时必须配置。忠告:Hibernate用不好会发出N多条sql语句,效率会大大降低。23、用Query或者save操作大量实体对象时给Session缓存中都会放一份,这样会影响效率,很可能内存溢出,所以大量数据操作不适合用hibernate。24、每次执行list()默认都会像数据库发出sql语句,但它会一次性把集合中的所有元素都查出来,它只会为一级缓存中放数据,但不会从缓存中取,而iterate()方法会先从缓存中取,如果缓存中没有就会很可能发生N+1问题。N+1问题:1-首先发出一条查询对象id列表的sql。N-根据id的列表一个一个去一级缓存中查找,如果没有就每个id发出一条sql,即N个id就发出N条查询语句。25、hibernate还支持HQL语句外置,即把HQL语句放到任何一个的hbm.xml映射文件中。26、hibernate还支持查询过滤器,即在相应的hbm.xml映射配置文件中配置条件后,在执行action中的HQL查询时就会自动加上映射文件中配置的条件。27、hibernate也带left join和right join,左连接就是左边表全部显示,右边为空的就显示null。右连接正好相反。28、HQL也支持DML风格语句,即用HQL的update、delete等,这个不建议使用,关键是我也没用过,嘿嘿。29、hibernate的抓取策略默认就是fetch=select,意思是用到关联对象时,会再发一条select查询语句。如果手动设置fetch=join抓取策略,Hibernate会通过一条select语句使用外连接直接查出实体对象和与其关联的对象或者集合(即使你不使用那些相关联的对象,照样会一次性查出来,影响效率)。Hibernate还有其他抓取策略,等用到了再去看吧!30、hibernate还可以配置批量查询、更新,即在配置文件中可以配置一个最大返回记录数,一般可以设为50,意思就是当你一次性查询10000条数据时,底层数据库都是50条50条的给你返回,这个功能需要特定的数据库支持才行。31、Hibernate的映射配置文件还是比较复杂,但它有注解配置,这个现在用的也非常多,个人也比较喜欢这种配置方式。32、最后再说下Hibernate还集成了一个测试工具类,junit这是个第三方库,只要我们写的类继承了TestCase,然后方法必须是公共的返回值为空,且方法名以小写test开头,不能带参数。(类名无限制,但推荐最好以大写的Test结尾),这样就可以很方便的进行测试了。下面贴出一些测试用例代码:第一、hibernate.cfg.cml是Hibernate的主配置文件(这个名字可以随便起):!DOCTYPE hibernate-configuration PUBLIC-/Hibernate/Hibernate Configuration DTD 3.0/EN!-配置与数据库连接有关的信息,并引入映射文件,此配置文件的属性都比较简单就不用再38了-hibernate-configuration session-factory property name=connection.driver_classoracle.jdbc.driver.OracleDriver/property property name=connection.urljdbc:oracle:thin:localhost:1521:ORCL9I/property property name=connection.usernametest/property property name=connection.passwordtest/property property name=dialectorg.hibernate.dialect.Oracle9Dialect/property!-下面这个属性配置成update后,则我们从新生成表时,没有改变的表将不会被drop(删了从建),只会新建有变动的表,而且这个属性设置后我们也不用hibernate的生成表工具(SchemaExport)去执行创建表,而是当我们插入数据时,hibernate会自动帮我们先创建表,再去插入数据。-property name=hbm2ddl.autoupdate/property property name=show_sqltrue/property mapping resource=many_to_many_shuangxiang/User.hbm.xml/mapping resource=many_to_many_shuangxiang/Role.hbm.xml/session-factory/hibernate-configuration第二、列出Hibernate中比较复杂的多对多双向关联映射配置(如果我是项目经理,这些对象的所有关心都不会配置,呵呵)就以用户和角色为例:1、用户的映射文件如下:?xml version=1.0?!DOCTYPE hibernate-mapping PUBLIC-/Hibernate/Hibernate Mapping DTD 3.0/EN!-加入这个package属性后,下面就不用写全包名了-hibernate-mapping package=many_to_many_shuangxiangclass name=Usertable=t_userid name=userIdgenerator class=sequence!-这里Id生成策略配成了oracle的序列,下面param参数名固定为sequence,然后值SEQ_USER是你提前建好的序列名字-param name=sequenceSEQ_USER/param/generator/id property name=userName/!-set中的table会创建个中间表-set name=rolestable=user_role!-下面这个key是中间表中的外键,引用当前表的主键-key column=userId/!-many-to-many中的column也是中间表的外键(中间表用的是复合主键),引用class属性中持久类Role对应表的主键-many-to-many class=Rolecolumn=roleId/set/class/hibernate-mapping 2、角色的映射文件如下:?xml version=1.0?!DOCTYPE hibernate-mapping PUBLIC-/Hibernate/Hibernate Mapping DTD 3.0/EN!-加入这个package属性后,下面就不用写全包名了-hibernate-mapping package=many_to_many_shuangxiangclass name=Roletable=t_roleid name=roleId!-这里id生成策略配成uuid即32位字符,这个也比较常用,因为不会重复。-generator class=uuid/id property name=roleName/set name=userstable=user_rolekey column=roleId/many-to-many class=Usercolumn=userId/set/class/hibernate-mapping第三、Hibernate根据持久化类(pojo+映射文件)去创建对应的数据库表:public static void main(String args)/加载hibernate的配置文件/Configuration cfg=new Configuration();这样会默认读取的是properties文件;Configuration cfg=new Configuration().configure();/调用了这个方法后才会默认去读取hibernate.cfg.xml配置文件。SchemaExport export=new SchemaExport(cfg);/用这个类就可以生成数据库表。export.create(true,true);/此方法生成表。第四、SessionFactory是个重量级对象,所以最好在整个系统就只创建一次,再给Session设计个单态模式:public class SessionUtilprivate static SessionFactory factory;private static Session session;staticConfiguration cfg=new Configuration().configure();factory=cfg.buildSessionFactory();session=factory.openSession();public static Session getSession()return session;public static void closeSession(Session session)if(session!=null)session.close();第五、Hibernate的增、删、改、查:增-session.save(user);删-session.delete(user),这个通常是先查出来改-session.update(user),同样是先查出来,此时可以不调用update(),set()修改完属性后直接提交事务就行了。查-session.load(user.class,id),session.get(user.class,id)个人比较喜欢用这种方式。;第六、列出常用的HQL查询语句:1、简单实体列表查询:/里面传的是HQL查询语言,这里的User类跟此类没在同一个包下,hibernate会默认找到User所在的包。Query query=session.createQuery(from User);List list=query.list();2、Hibernate分页查询:/里面传的是HQL查询语言,查询的直接是对象集合。Query query=session.createQuery(from User uorder by u.userName);query.setFirstResult(0);/设置从库中第一条数据开始查询,即传0,在数据库中是从0开始的。query.setMaxResults(2);/设置每次查询的记录数为2,即查询的对象个数。List list=query.list();3、单个实体查询:User user=(User)session.createQuery(from User as uwhere u.userId=uuid1).uniqueResult();4、对象属性查询(直接用iterate()方法):Iterator iterator=session.createQuery(select u.userName from User uwhere u.userId=?and u.userName=?).setString(0,8a 88831127f5fd8d0127f5fd90b20003).setString(1,马文涛)/这两个参数就可以从页面传过来.iterate();while(iterator.hasNext()String userName=(String)iterator.next();System.out.println(userName);5、使用where、like、分组、过滤、排序、内置函数进行条件查询List list=session.createQuery(select count(u),u.userName from User uwhere u.userName+like%文%group by u.userName having count(u)2 order by u.userName).list();for(Iterator i=list.iterator();i.hasNext();)Object o=(Object)i.next();long count=(Long)o0;/这个count()返回的类型是long,不能用int接受
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 文化体育用品公司合伙协议书
- 幸福新山安全培训课件
- 巡湖安全培训方案课件
- 岩石课件X教学课件
- 输电线路巡视课件
- 输液通路疑难病例课件
- 小鸭子喝水课件
- 文化活动拱门空飘布置安装合同
- 供应链金融担保付款合作协议书
- 爆炸事故遇难者家属赔偿金合同
- 林则徐虎门销烟课件
- QC/T 1206.2-2024电动汽车动力蓄电池热管理系统第2部分:液冷系统
- -思想政治教育学原理课件(精品课件)
- 中国驻外领使馆地区分类
- 幼儿园教师读书笔记记录表
- 煤矿群监员培训
- 大学英语四级写作技巧及模板
- T-SZTIA 003-2020 抗菌口罩标准规范
- 颈动脉保护装选择
- 2023年东台市城市建设投资发展集团有限公司招聘笔试题库及答案解析
- 可测试性设计DFT课件
评论
0/150
提交评论