ImageVerifierCode 换一换
格式:DOCX , 页数:22 ,大小:23.65KB ,
资源ID:9571883      下载积分:1 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-9571883.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Hibernate课堂笔记.docx)为本站会员(b****0)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

Hibernate课堂笔记.docx

1、Hibernate课堂笔记Hibernate课堂笔记一、 Hibernate环境搭建1) Hibernate3最后一个版本Hibernate3.6.10的环境搭建1、导入项目所需要的包hibernate3.jar,lib/required下的所有包和lib/jpa下的包2、编写配置文件和映射文件参考documentationmanualzh-CNhtml_single1.1.4. Hibernate 配置1.1.3. 映射文件3、创建SessionFactory和Sessionpublic class HibernateUtil private static SessionFactory se

2、ssionFactory = null; static sessionFactory = new Configuration().configure().buildSessionFactory(); public Session getSession() return sessionFactory.openSession(); 2) 截至目前为止,Hibernate4最新版本Hibernate4.3.8的环境搭建1、导入项目所需要的包lib/required下的所有包2、编写配置文件和映射文件参考documentationmanualen-UShtml_single1.1.4. Hiberna

3、te configuration1.1.3. The mapping file3、创建SessionFactory和Sessionpublic class HibernateUtil private static SessionFactory sessionFactory = null; static Configuration cfg = new Configuration().configure(); ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties().bui

4、ld(); sessionFactory = cfg.buildSessionFactory(serviceRegistry); public Session getSession() return sessionFactory.openSession();二、 Hibernate对象三种状态Hibernate中的对象有三种状态: 瞬时状态 (Transient),持久状态 (Persistent), 脱管状态 (Detached) 瞬时状态 (Transient)由 new 命令开辟内存空间的 Java 对象,也就是平时所熟悉的普通 Java 对象。如: Student stu = new

5、Student();瞬时对象特点:(1) 不和 Session 实例关联(2) 在数据库中没有和瞬时对象关联的记录 持久状态 (Persistent)持久的实例在数据库中有对应的记录,并拥有一个持久化标识 (identifier).持久对象总是与 Session 和 Transaction 相关联,在一个 Session 中,对持久对象的改变不会马上对数据库进行变更,而必须在Transaction 终止,也就是执行 commit() 之后,才在数据库中真正运行 SQL 进行变更,持久对象的状态才会与数据库进行同步。在同步之前的持久对象称为脏 (dirty) 对象。瞬时对象转为持久对象:(1)

6、通过 Session 的 save() 和 saveOrUpdate() 方法把一个瞬时对象与数据库相关联,这个瞬时对象就成为持久化对象。(2) 使用 get(),load() 待方法查询到的数据对象,将成为持久化对象。持久化对象的特点:(1) 和 Session 实例关联(2) 在数据库中有和持久对象关联的记录 脱管状态 (Detached)与持久对象关联的 Session 被关闭后,对象就变为脱管对象。对脱管对象的引用依然有效,对象可继续被修改。脱管对象特点:(1) 本质上和瞬时对象相同(2) 只是比瞬时对象多了一个数据库记录标识值 id.持久对象转为脱管对象:当执行 close() 或

7、clear(),evict() 之后,持久对象会变为脱管对象。瞬时对象转为持久对象:通过 Session 的 update(),saveOrUpdate() 和 lock() 等方法,把脱管对象变为持久对象。4 结合 save(),update(),saveOrUpdate() 方法说明对象的状态(1)Save() 方法将瞬时对象保存到数据库,对象的临时状态将变为持久化状态。当对象在持久化状态时,它一直位于 Session 的缓存中,对它的任何操作在事务提交时都将同步到数据库,因此,对一个已经持久的对象调用 save() 或 update() 方法是没有意义的。如:Student stu =

8、new Strudnet();stu.setCarId(“200234567”);stu.setId(“100”);/ 打开 Session, 开启事务session.save(stu);stu.setCardId(“20076548”);session.save(stu); / 无效session.update(stu); / 无效/ 提交事务,关闭 Session(2)update() 方法两种用途重新关联脱管对象为持久化状态对象,显示调用 update() 以更新对象。调用 update() 只为了关联一个脱管对象到持久状态,当对象已经是持久状态时,调用 update() 就没有多大意义

9、了。如:/ 打开 session ,开启事务 stu = (Student)session.get(Student.class,”123456”);stu.setName(“Body”);session.update(stu); / 由于 stu 是持久对象,必然位于 Session 缓冲中,对 stu 所做的变更将 / 被同步到数据库中。所以 update() 是没有意义的,可以不要这句效果一样的。/ 提交事务,关闭 SessionHibernate 总是执行 update 语句,不管这个脱管对象在离开 Session 之后有没有更改过,在清理缓存时 Hibernate 总是发送一条upda

10、te 语句,以确保脱管对象和数据库记录的数据一致,如:Student stu = new Strudnet();stu.setCarId(“1234”);/ 打开 Session1, 开启事务session1.save(stu);/ 提交事务,关闭 Session1stu.set(“4567”); / 对脱管对象进行更改/ 打开 Session2, 开启事务session2.update(stu);/ 提交事务,关闭 Session2如果希望只有脱管对象改变了, Hibernate 才生成 update 语句,可以把映射文件中 标签的 select-before-update 设为true,

11、这种会先发送一条 select 语句取得数据库中的值,判断值是否相同,如果相同就不执行 update 语句。不过这种做法有一定的缺点,每次 update 语句之前总是要发送一条多余的 select 语句,影响性能。对于偶尔更改的类,设置才是有效的,对于经常要更改的类这样做是影响效率的。(3)saveOrUpdate() 方法兼具 save() 和 update() 方法的功能,对于传入的对象, saveOrUpdate() 首先判断其是脱管对象还是临时对象,然后调用合适的方法。三、 load和get的区别hibernate延迟加载(get和load的区别) 1.load加载方式当使用load方

12、法来得到一个对象时,此时hibernate会使用延迟加载的机制来加载这个对象,即:当我们使用session.load()方法来加载一个对象时,此时并不会发出sql语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的id值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出sql语句,从数据库中去查询我们的对象。session = HibernateUtil.openSession(); /* * 通过load的方式加载对象时,会使用延迟加载机制,此时并不会发出sql语句,只有当我们需要使用的时候才会从数据库中去查询 */ User user = (User)ses

13、sion.load(User.class, 2);我们看到,如果我们仅仅是通过load来加载我们的User对象,此时从控制台我们会发现并不会从数据库中查询出该对象,即并不会发出sql语句,但如果我们要使用该对象时:session = HibernateUtil.openSession();User user = (User)session.load(User.class, 2);System.out.println(user);此时我们看到控制台会发出了sql查询语句,会将该对象从数据库中查询出来这个时候我们可能会想,那么既然调用load方法时,并不会发出sql语句去从数据库中查出该对象,那么

14、这个User对象到底是个什么对象呢?其实这个User对象是我们的一个代理对象,这个代理对象仅仅保存了id这个属性:session = HibernateUtil.openSession(); /* * 通过load的方式加载对象时,会使用延迟加载机制,此时得到的User对象其实是一个 * 代理对象,该代理对象里面仅仅只有id这个属性 */ User user = (User)session.load(User.class, 2); System.out.println(user.getId();我们看到,如果我们只打印出这个user对象的id值时,此时控制台会打印出该id值,但是同样不会发出s

15、ql语句去从数据库中去查询。这就印证了我们的这个user对象仅仅是一个保存了id的代理对象,但如果我需要打印出user对象的其他属性值时,这个时候会不会发出sql语句呢?答案是肯定的: session = HibernateUtil.openSession(); /* * 通过load的方式加载对象时,会使用延迟加载机制,此时得到的User对象其实是一个 * 代理对象,该代理对象里面仅仅只有id这个属性 */ User user = (User)session.load(User.class, 2); System.out.println(user.getId(); / 如果此时要得到user

16、其他属性,则会从数据库中查询 System.out.println(user.getUsername(); 相信通过上述的几个例子,大家应该很好的了解了load的这种加载对象的方式了吧。2、get加载方式相对于load的延迟加载方式,get就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出sql语句去从数据库中查询出来:session = HibernateUtil.openSession(); /* * 通过get方法来加载对象时,不管使不使用该对象,都会发出sql语句,从数据库中查询 */ User user = (User)ses

17、sion.get(User.class, 2);此时我们通过get方式来得到user对象,但是我们并没有使用它,但是我们发现控制台会输出sql的查询语句因此我们可以看到,使用load的加载方式比get的加载方式性能要好一些,因为load加载时,得到的只是一个代理对象,当真正需要使用这个对象时再去从数据库中查询。3、使用get和load时的一些小问题当了解了load和get的加载机制以后,我们此时来看看这两种方式会出现的一些小问题:如果使用get方式来加载对象,当我们试图得到一个id不存在的对象时,此时会报NullPointException的异常 session = HibernateUtil

18、.openSession(); /* * 当通过get方式试图得到一个id不存在的user对象时,此时会报NullPointException异常 */ User user = (User)session.get(User.class, 20); System.out.println(user.getUsername();此时我们看控制台的输出信息,会报空指针的异常这是因为通过get方式我们会去数据库中查询出该对象,但是这个id值不存在,所以此时user对象是null,所以就会报NullPointException的异常了。如果使用load方式来加载对象,当我们试图得到一个id不存在的对象时,

19、此时会报ObjectNotFoundException异常:复制代码session = HibernateUtil.openSession(); /* * 当通过get方式试图得到一个id不存在的user对象时,此时会报ObjectNotFoundException异常 */ User user = (User)session.load(User.class, 20); System.out.println(user.getId(); System.out.println(user.getUsername();为什么使用load的方式和get的方式来得到一个不存在的对象报的异常不同呢?其原因还

20、是因为load的延迟加载机制,使用load时,此时的user对象是一个代理对象,仅仅保存了当前的这个id值,当我们试图得到该对象的username属性时,这个属性其实是不存在的,所以就会报出ObjectNotFoundException这个异常了。org.hibernate.LazyInitializationException异常接下来我们再来看一个例子:public class UserDAO public User loadUser(int id) Session session = null; Transaction tx = null; User user = null; try s

21、ession = HibernateUtil.openSession(); tx = session.beginTransaction(); user = (User)session.load(User.class, 1); mit(); catch (Exception e) e.printStackTrace(); tx.rollback(); finally HibernateUtil.close(session); return user; Test public void testLazy06() UserDAO userDAO = new UserDAO(); User user

22、= userDAO.loadUser(2); System.out.println(user); 模拟了一个UserDAO这样的对象,然后我们在测试用例里面来通过load加载一个对象,此时我们发现控制台会报LazyInitializationException异常org.hibernate.LazyInitializationException: could not initialize proxy - no Session.这个异常是什么原因呢?还是因为load的延迟加载机制,当我们通过load()方法来加载一个对象时,此时并没有发出sql语句去从数据库中查询出该对象,当前这个对象仅仅是一个

23、只有id的代理对象,我们还并没有使用该对象,但是此时我们的session已经关闭了,所以当我们在测试用例中使用该对象时就会报LazyInitializationException这个异常了。所以以后我们只要看到控制台报LazyInitializationException这种异常,就知道是使用了load的方式延迟加载一个对象了,解决这个的方法有两种,一种是将load改成get的方式来得到该对象,另一种是在表示层来开启我们的session和关闭session。总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,

24、如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。四、 Hibernate主键生成策略Hibernate各种主键生成策略与配置详解1、assigned主键由外部程序负责生成,在 save() 之前必须指定一个。Hibernate不负责维护主键生成。与Hibernate和底层数据库都无关,可以跨数据库。在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免。特点:可以跨数据库,人为控制主键生成,应尽量避免。2、increment由Hibernate从数据库中取出主键的最

25、大值(每个session只取1次),以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库,因此可以跨数据库。Hibernate调用org.hibernate.id.IncrementGenerator类里面的generate()方法,使用select max(idColumnName) from tableName语句获取主键最大值。该方法被声明成了synchronized,所以在一个独立的Java虚拟机内部是没有问题的,然而,在多个JVM同时并发访问数据库select max时就可能取出相同的值,再insert就会发生Dumplicate entry的错误。所以只能有一个Hib

26、ernate应用进程访问数据库,否则就可能产生主键冲突,所以不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。官方文档:只有在没有其他进程往同一张表中插入数据时才能使用,在集群下不要使用。特点:跨数据库,不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。3、hilohilo(高低位方式high low)是hibernate中最常用的一种生成方式,需要一张额外的表保存hi的值。保存hi值的表至少有一条记录(只与第一条记录有关),否则会出现错误。可以跨数据库。hibernate_hilonext_hi100hibernate_hilo 指定保存hi值的表名n

27、ext_hi 指定保存hi值的列名100 指定低位的最大值也可以省略table和column配置,其默认的表为hibernate_unique_key,列为next_hi100hilo生成器生成主键的过程(以hibernate_unique_key表,next_hi列为例):1. 获得hi值:读取并记录数据库的hibernate_unique_key表中next_hi字段的值,数据库中此字段值加1保存。2. 获得lo值:从0到max_lo循环取值,差值为1,当值为max_lo值时,重新获取hi值,然后lo值继续从0到max_lo循环。3. 根据公式 hi * (max_lo + 1) + lo

28、计算生成主键值。注意:当hi值是0的时候,那么第一个值不是0*(max_lo+1)+0=0,而是lo跳过0从1开始,直接是1、2、3那max_lo配置多大合适呢?这要根据具体情况而定,如果系统一般不重启,而且需要用此表建立大量的主键,可以吧max_lo配置大一点,这样可以减少读取数据表的次数,提高效率;反之,如果服务器经常重启,可以吧max_lo配置小一点,可以避免每次重启主键之间的间隔太大,造成主键值主键不连贯。特点:跨数据库,hilo算法生成的标志只能在一个数据库中保证唯一。4、seqhilo与hilo类似,通过hi/lo算法实现的主键生成机制,只是将hilo中的数据表换成了序列sequence,需要数据库中先创建sequence,适用于支持sequence的数据库,如Oracle。hibernate_seq100 特点:与hilo类似,只能在支持序列的数据库中使用。5、sequence采用数据库提供的sequence机制生成主键,需要数据库支持sequence。如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence。MySQL这种不支持sequence的数据库则不行(可以使用identity)。hibe

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2