文档库 最新最全的文档下载
当前位置:文档库 › Hibernate的flush机制

Hibernate的flush机制

Hibernate的flush机制
Hibernate的flush机制

浅谈hibernate的flush机制

博客分类:

Hibernate

Hibernate多线程.netAccess

随着Hibernate在Java开发中的广泛应用,我们在使用Hibernate进行对象持久化操作中也遇到了各种各样的问题。这些问题往往都是我们对Hibernate缺乏了解所致,这里我讲个我从前遇到的问题及一些想法,希望能给大家一点借鉴。

这是在一次事务提交时遇到的异常。

an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)

net.sf.hibernate.AssertionFailure: possible nonthreadsafe access to session

注:非possible non-threadsafe access to the session (那是另外的错误,类似但不一样)

这个异常应该很多的朋友都遇到过,原因可能各不相同。但所有的异常都应该是在flush或者事务提交的过程中发生的。这一般由我们在事务开始至事务提交的过程中进行了不正确的操作导致,也会在多线程同时操作一个Session时发生,这里我们仅仅讨论单线程的情况,多线程除了线程同步外基本与此相同。

至于具体是什么样的错误操作那?我给大家看一个例子(假设Hibernate配置正确,为保持代码简洁,不引入包及处理任何异常)

Java代码

1.SessionFactory sf = new

Configuration().configure().buildSessionFactory() ;

2.Session s = sf.openSession();

3.Cat cat = new Cat();

4.

5.Transaction tran = s.beginTransaction(); /(1)

6.s.save(cat);// (2)(此处同样可以为update delete)

7.s.evict(cat); //(3)

https://www.wendangku.net/doc/b02142383.html,mit();// (4)

9.s.close();//(5)

这就是引起此异常的典型错误。我当时就遇到了这个异常,检查代码时根本没感觉到这段代码出了问题,想当然的认为在Session上开始一个事务,通过Session 将对象存入数据库,再将这个对象从Session上拆离,提交事务,这是一个很正常的流程。如果这里正常的话,那问题一定在别处。

问题恰恰就在这里,我的想法也许没有错,但是一个错误的论据所引出的观点永远都不可能是正确的。因为我一直以为直接在对数据库进行操作,忘记了在我与数据库之间隔了一个Hibernate,Hibernate在为我们提供持久化服务的同时,也改变了我们对数据库的操作方式,这种方式与我们直接的数据库操作有着很多的不同,正因为我们对这种方式没有一个大致的了解造成了我们的应用并未得到预先设想的结果。

那Hibernate的持久化机制到底有什么不同那?简单的说,Hibernate在数据库层之上实现了一个缓存区,当应用save或者update一个对象时,Hibernate并未将这个对象实际的写入数据库中,而仅仅是在缓存中根据应用的行为做了登记,在真正需要将缓存中的数据flush入数据库时才执行先前登记的所有行为。

在实际执行的过程中,每个Session是通过几个映射和集合来维护所有与该Session建立了关联的对象以及应用对这些对象所进行的操作的,与我们这次讨论有关的有entityEntries(与Session相关联的对象的映射)、insertions(所有的插入操作集合)、deletions(删除操作集合)、updates(更新操作集合)。下面我就开始解释在最开始的例子中,Hibernate到底是怎样运作的。

(1)生成一个事务的对象,并标记当前的Session处于事务状态(注:此时并未启动数据库级事务)。

(2)应用使用s.save保存cat对象,这个时候Session将cat这个对象放入entityEntries,用来标记cat已经和当前的会话建立了关联,由于应用对cat

做了保存的操作,Session还要在insertions中登记应用的这个插入行为(行

为包括:对象引用、对象id、Session、持久化处理类)。

(3)s.evict(cat)将cat对象从s会话中拆离,这时s会从entityEntries中将cat这个对象移出。

(4)事务提交,需要将所有缓存flush入数据库,Session启动一个事务,并按

照insert,update,……,delete的顺序提交所有之前登记的操作(注意:所有insert执行完毕后才会执行update,这里的特殊处理也可能会将你的程序搞得一团糟,如需要控制操作的执行顺序,要善于使用flush),现在cat不在entityEntries中,但在执行insert的行为时只需要访问insertions就足够了,所以此时不会有任何的异常。异常出现在插入后通知Session该对象已经插入完毕这个步骤上,这个步骤中需要将entityEntries中cat的existsInDatabase

标志置为true,由于cat并不存在于entityEntries中,此时Hibernate就认

为insertions和entityEntries可能因为线程安全的问题产生了不同步(也不知道Hibernate的开发者是否考虑到例子中的处理方式,如果没有的话,这也许算是一个bug吧),于是一个net.sf.hibernate.AssertionFailure就被抛出,程序终止。

我想现在大家应该明白例子中的程序到底哪里有问题了吧,我们的错误的认为

s.save会立即的执行,而将cat对象过早的与Session拆离,造成了Session 的insertions和entityEntries中内容的不同步。所以我们在做此类操作时一定要清楚Hibernate什么时候会将数据flush入数据库,在未flush之前不要将已进行操作的对象从Session上拆离。

对于这个错误的解决方法是,我们可以在(2)和(3)之间插入一个s.flush()强制Session将缓存中的数据flush入数据库(此时Hibernate会提前启动事务,将(2)中的save登记的insert语句登记在数据库事务中,并将所有操作集合清空),这样在(4)事务提交时insertions集合就已经是空的了,即使我们拆离了cat

也不会有任何的异常了。

前面简单的介绍了一下Hibernate的flush机制和对我们程序可能带来的影响以及相应的解决方法,Hibernate的缓存机制还会在其他的方面给我们的程序带来一些意想不到的影响。看下面的例子:

(name为cat表的主键)

Java代码

1.Cat cat = new Cat();

2.cat.setName(“tom”);

3.s.save(cat);

4.

5.cat.setName(“mary”);

6.s.update(cat);(6)

7.

8.Cat littleCat = new Cat();

9.littleCat.setName(“tom”);

10.s.save(littleCat);

11.

12.s.flush();

这个例子看起来有什么问题?估计不了解Hibernate缓存机制的人多半会说没有问题,但它也一样不能按照我们的思路正常运行,在flush过程中会产生主键冲突,可能你想问:“在save(littleCat)之前不是已经更改https://www.wendangku.net/doc/b02142383.html,并已经更新了么?为什么还会发生主键冲突那?”这里的原因就是我在解释第一个例子时所提到的缓存flush顺序的问题,Hibernate按照

insert,update,……,delete的顺序提交所有登记的操作,所以你的

s.update(cat)虽然在程序中出现在s.save(littleCat)之前,但是在flush的过程中,所有的save都将在update之前执行,这就造成了主键冲突的发生。

这个例子中的更改方法一样是在(6)之后加入s.flush()强制Session在保存littleCat之前更新cat的name。这样在第二次flush时就只会执行

s.save(littleCat)这次登记的动作,这样就不会出现主键冲突的状况。

再看一个例子(很奇怪的例子,但是能够说明问题)

Java代码

1.Cat cat = new Cat();

2.cat.setName(“tom”);

3.s.save(cat); (7)

4.s.delete(cat);(8)

5.

6.cat.id=null;(9)

7.s.save(cat);(10)

8.s.flush();

这个例子在运行时会产生异常net.sf.hibernate.HibernateException: identifier of an instance of Cat altered from

8b818e920a86f038010a86f03a9d0001 to null

这里例子也是有关于缓存的问题,但是原因稍有不同:

(7)和(2)的处理相同。

(8)Session会在deletions中登记这个删除动作,同时更新entityEntries 中该对象的登记状态为DELETED。

(9)Cat类的标识符字段为id,将其置为null便于重新分配id并保存进数据库。(10)此时Session会首先在entityEntries查找cat对象是否曾经与Session 做过关联,因为cat只改变了属性值,引用并未改变,所以会取得状态为DELETED 的那个登记对象。由于第二次保存的对象已经在当前Session中删除,save会强制Session将缓存flush才会继续,flush的过程中首先要执行最开始的save 动作,在这个save中检查了cat这个对象的id是否与原来执行动作时的id相同。不幸的是,此时cat的id被赋为null,异常被抛出,程序终止(此处要注意,我们在以后的开发过程尽量不要在flush之前改变已经进行了操作的对象的id)。

这个例子中的错误也是由于缓存的延时更新造成的(当然,与不正规的使用Hibernate也有关系),处理方法有两种:

1、在(8)之后flush,这样就可以保证(10)处save将cat作为一个全新的对象进行保存。

2、删除(9),这样第二次save所引起的强制flush可以正常的执行,在数据库中插入cat对象后将其删除,然后继续第二次save重新插入cat对象,此时cat的id仍与从前一致。

这两种方法可以根据不同的需要来使用,呵呵,总觉得好像是很不正规的方式来解决问题,但是问题本身也不够正规,只希望能够在应用开发中给大家一些帮助,不对的地方也希望各位给与指正。

总的来说,由于Hibernate的flush处理机制,我们在一些复杂的对象更新和保存的过程中就要考虑数据库操作顺序的改变以及延时flush是否对程序的结果有影响。如果确实存在着影响,那就可以在需要保持这种操作顺序的位置加入flush强制Hibernate将缓存中记录的操作flush入数据库,这样看起来也许不太美观,但很有效。

hibernate练习题

1.下面创建Criteria对象的语句中正确的是 单选 A、Criteria c = query.createCriteria(); B、Criteria c = query.addCriteria(); C、Criteria c = session.createCriteria(); D、Criteria c = session.createCriteria(User.class); 2. Query对象执行查询结论正确的是 多选 A、list()方法返回结果为List对象,数据总量为0到多条 B、uniqueResut()方法返回结果为对象或对象数组,数据总量为0到1条数据 C、HQL:select userName from UserModel可以使用list()方法进行查询结果的获取 D、HQL:select userName from UserModel可以使用uniqueResut()方法进行查询结果的获取 3Hibernate实体对象制作规范不包含下列哪条规则 单选 A、声明无参公共的构造方法 B、提供用于作为OID的标识属性 C、为所有属性提供getter与setter方法 D、声明为最终类(final修饰) 4在HQL语句的参数查询中,执行以下代码,下列选项能够为参数正确赋值的操作是Query query = s.createQuery("from Customer o where https://www.wendangku.net/doc/b02142383.html,=?"); 单选 A、query.setParameter(1, "Tom"); B、query.setParameter(0, "Tom"); C、query.setString(0,Tom); D、query.setInteger (0,Tom); 5有关Hibernate瞬时对象状态说法错误的是 多选 A、瞬时状态的对象具有OID,与Session对象关联 B、瞬时状态的对象具有OID,不与Session对象关联 C、瞬时状态的对象不具有OID,与Session对象关联 D、瞬时状态的对象不具有OID,不与Session对象关联 6有关QBC查询短语,下列说法正确的 多选 A、Restrictions.between表示范围比对 B、Restrictions.eq表示等比对 C、Restrictions.le表示小于等于比对 D、Restrictions.ge表示大于等于比对 7下列操作对一级缓存的影响描述错误的是

缓存机制

3.1、缓存策略 3.1.1、一级缓存 之前每一个数据库操作都是一个Session,那么对于Session来说本身是存在着缓存,可以保留之前的查询结果。 但是对于Session的缓存只针对于一个Session有效,那么如果现在想针对于多个Session 有作用,则必须在SessionFactory上配置缓存,那么这样的缓存称为二级缓存。 在Hiernate按ID查询有两个方法:load、get 那么下面使用以上的查询方法,查询两次 程序虽然调用了两次load方法,但是只发出了一条的查询命令,证明,第一次的查询结果被保存下来了,那么这就是一级缓存。

与之前的相比,查询了两次操作,所以此时,证明一级缓存只是针对于一个Session起作用的。但是一级缓存是无法关闭的,始终会存在。

从运行结果可以发现,如果之前先进行了保存操作,那么之后再查询的话也不会重新发出查询语句。证明实体被缓存下来。 问题: 如果现在要求使用程序插入100000万条记录?该怎么办? 如果使用Hibernate处理的话,则可能会出现内存的溢出,所以在这种情况下首先是绝对不建议使用Hibernate完成的,就使用最基本的JDBC操作完成即可。 如果非要使用Hibernate做,则必须使用到Session中关于缓存的一些操作方法:·清空Session中的所有缓存:clear() ·清空Session中一个指定的实体:evict(Object obj) 例如:下面验证clear()方法 因为程序中,将所有的缓存清空了,所以之后再查询相同实体的时候,在Session中已

以上因为只清空了一个实体,所以只发出了三个查询语句。 那么就可以通过以上的方式完成100W条记录的插入 思路:按照每十条清空缓存的操作,并将缓存中的内容强制性的写到数据库之中 3.1.2、二级缓存(重点) 在Hibernate本身中支持了多种的二级缓存组件。本次使用EHcache。如果要想使用ehcache话,则首先必须进行配置,配置ehcache的缓存文件。 ehcache.xml:

hibernate配置数据库连接池的三种方法

?数据库连接池的概念(是什么,做什么用的,有什么好处) ?首先,我们还是老套的讲讲连接池的基本概念,概念理解清楚了,我们也知道后面是怎么回事了。?以前我们程序连接数据库的时候,每一次连接数据库都要一个连接,用完后再释放。如果频繁的数据库操作,就会导致性能很低。连接池的出现,为开发过程提供了一个很好的管理平台。当程序中需要建立数据库连接时,只须从内存中取一个来用而不用新建。同样,使用完毕后,只需放回内存即可。而连接的建立、断开都有连接池自身来管理。同时,我们还可以通过设置连接池的参数来控制连接池中的连接数、每个连接的最大使用次数等等。通过使用连接池,将大大提高程序效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。 ?而Hibernate的出现把连接池的使用引入了一个新的利用方式,让你充分享受配置化给开发带来的便利。 1 C3P0 (以验证可用) 只需在hibernate.cfg.xml中加入 omdssd_admin omdssd_hskj jdbc:oracle:thin:@10.142.1.138:1521:omds oracle.jdbc.driver.OracleDriver org.hibernate.dialect.Oracle9Dialect true true oracle10g_112 org.hibernate.connection.C3P0ConnectionProvider 5 //连接池中数据库连接的最小数目 30 //连接池中数据库连接的最大数目 1800 //设定数据库连接的过期时间,以秒为单位 50 //可以被缓存的PreparedStatement实例的最大数目。缓存适量的PreparedStatement实例,能够大大提高Hibernate的性能。 120//在使数据库连接自动生效之前处于空闲状态的时间,以秒为单位

Hibernate性能调优

Hibernate性能调优 关键字: hibernate性能调优 一、inverse = ? inverse=false(default) 用于单向one-to-many关联 parent.getChildren().add(child) // insert child parent.getChildren().delete(child) // delete child inverse=true 用于双向one-to-many关联 child.setParent(parent); session.save(child) // insert child session.delete(child) 在分层结构的体系中 parentDao, childDao对于CRUD的封装导致往往直接通过session接口持久化对象,而很少通过关联对象可达性 二、one-to-many关系 单向关系还是双向关系? parent.getChildren().add(child)对集合的触及操作会导致lazy的集合初始化,在没有对集合配置二级缓存的情况下,应避免此类操作 select * from child where parent_id = xxx; 性能口诀: 1. 一般情况下避免使用单向关联,尽量使用双向关联

2. 使用双向关联,inverse=“true” 3. 在分层结构中通过DAO接口用session直接持久化对象,避免通过关联关系进行可达性持久化 三、many-to-one关系 单向many-to-one表达了外键存储方 灵活运用many-to-one可以避免一些不必要的性能问题 many-to-one表达的含义是:0..n : 1,many可以是0,可以是1,也可以是n,也就是说many-to-one可以表达一对多,一对一,多对一关系 因此可以配置双向many-to-one关系,例如: 1. 一桌四人打麻将,麻将席位和打麻将的人是什么关系?是双向many-to-one的关系 四、one-to-one 通过主键进行关联 相当于把大表拆分为多个小表 例如把大字段单独拆分出来,以提高数据库操作的性能 Hibernate的one-to-one似乎无法lazy,必须通过bytecode enhancement 五、集合List/Bag/Set

JAVA复试问题答案

(一) JAVA复试的问题整理 1 Hibernate 的优化流程是如何实现的,流程是怎么样? 1.尽量使用many-to-one,避免使用单向one-to-many 2.灵活使用单向one-to-many 3.不用一对一,使用多对一代替一对一 4.配置对象缓存,不使用集合缓存 5.一对多使用Bag 多对一使用Set 6.继承使用显示多态 HQL:from object polymorphism="exlicit" 避免查处所有对象 7.消除大表,使用二级缓存 2 Struts1与Struts2的区别? 在Action 实现类方面的对比:Struts 1 要求Action 类继承一个抽象基类;Struts 1 的一个具体问题是使用抽象类编程而不是接口。Struts 2 Action 类可以实现一个Action 接口,也可以实现其他接口,使可选和定制的服务成为可能。Struts2 提供一ActionSupport 基类去实现常用的接口。即使 Action 接口不是必须实现的,只有一个包含execute 方法的POJO 类都可以用作 Struts 2 的Action 。 线程模式方面的对比:Struts 1 Action 是单例模式并且必须是线程安全的,因为仅有Action 的一个实例来处理所有的请求。单例策略限制了Struts 1 Action 能做的事,并且要在开发时特别小心。Action 资源必须是线程安全的或同步的;Struts 2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。 Servlet 依赖方面的对比:Struts 1 Action 依赖于 Servlet API,因为Struts 1 Action 的execute 方法中有HttpServletRequest 和HttpServletResponse 方法。Struts 2 Action 不再依赖于 Servlet API,从而允许Action 脱离Web 容器运行,从而降低了测试Action 的难度。当然,如果Action 需要直接访问HttpServletRequest 和HttpServletResponse 参数,Struts 2 Action 仍然可以访问它们。但是,大部分时候,Action 都无需直接访问HttpServetRequest 和HttpServletResponse,从而给开发者更多灵活的选择。 可测性方面的对比:测试Struts 1 Action 的一个主要问题是execute 方法依赖于Servlet API,这使得Action 的测试要依赖于Web 容器。为了脱离Web 容器测试 Struts1

Hibernate_测试题

medal.setType("Gold Medal"); session.save(user); session.close(); } A.配置文件配置有误 B.没有在配置文件中包含对映射文件的声明 C.映射文件配置有误 D.没有开启事务 5.下列属于多对一关系的是(bd )。(选两项) A.书和作者 B.手机和生产厂家 C.用户和发布的出租信息 D.士兵和班长 6.下面是某系统中的两个实体类,依此可以得知(b )。 public class Wage{ //月工资实体类 private Long wid; private String empName; //雇员姓名 private String month; //月份 //Getter & Setter …… } public class WageItem{ //工资项 private Wage wage; private Long iid; private String itemName; //项目名称,如基本工资、职位津贴等private String amount; //数额 //Getter & Setter …… } A.Wage 和WageItem 间存在单向一对多的关联 B.Wage 和WageItem 间存在单向多对一的关联 C.Wage 和WageItem间存在双向一对多的关联 D.Wage 和WageItem间存在双向多对一的关联 7.两实体类代码如下: public class Wage{ //月工资实体类 private Long wid; private String empName; //雇员姓名 private String month; //月份 //Getter & Setter …… } public class WageItem{ //工资项 private Wage wage;

2019最新Java面试题,常见面试题及答案汇总

ava最新常见面试题+ 答案汇总 1、面试题模块汇总 面试题包括以下十九个模块:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM 。如下图所示: 可能对于初学者不需要后面的框架和JVM 模块的知识,读者朋友们可根据自己的情况,选择对应的模块进行阅读。 适宜阅读人群 需要面试的初/中/高级java 程序员 想要查漏补缺的人 想要不断完善和扩充自己java 技术栈的人 java 面试官 具体面试题 下面一起来看208 道面试题,具体的内容。 一、Java 基础 1.JDK 和JRE 有什么区别? 2.== 和equals 的区别是什么? 3.两个对象的hashCode()相同,则equals()也一定为true,对吗? 4.final 在java 中有什么作用? 5.java 中的Math.round(-1.5) 等于多少? 6.String 属于基础的数据类型吗? 7.java 中操作字符串都有哪些类?它们之间有什么区别? 8.String str="i"与String str=new String(“i”)一样吗? 9.如何将字符串反转? 10.String 类的常用方法都有那些? 11.抽象类必须要有抽象方法吗? 12.普通类和抽象类有哪些区别? 13.抽象类能使用final 修饰吗?

14.接口和抽象类有什么区别? 15.java 中IO 流分为几种? 16.BIO、NIO、AIO 有什么区别? 17.Files的常用方法都有哪些? 二、容器 18.java 容器都有哪些? 19.Collection 和Collections 有什么区别? 20.List、Set、Map 之间的区别是什么? 21.HashMap 和Hashtable 有什么区别? 22.如何决定使用HashMap 还是TreeMap? 23.说一下HashMap 的实现原理? 24.说一下HashSet 的实现原理? 25.ArrayList 和LinkedList 的区别是什么? 26.如何实现数组和List 之间的转换? 27.ArrayList 和Vector 的区别是什么? 28.Array 和ArrayList 有何区别? 29.在Queue 中poll()和remove()有什么区别? 30.哪些集合类是线程安全的? 31.迭代器Iterator 是什么? 32.Iterator 怎么使用?有什么特点? 33.Iterator 和ListIterator 有什么区别? 34.怎么确保一个集合不能被修改?

hibernate数据修改后不能及时更新 -

主要表现在新增、修改数据后,在数据列表中不能显示刚插入数据的关联对象的信息(新增插入或修改的数据主数据能显示,只有关联的数据不能显示),但刷新后能显示,再刷新可能又显示不出来了。随机的能显示或不能显示。搞不懂。 当你手动修改了数据库,Hibernate缓存中的数据就有可能是过期的。为了保证Hibernate与数据库一致,一般的 做法是在手动修改数据库之后,使用Hibernate查询数据之前,清空缓存。也就是说,你应该在执行查询前,调用 session.clear(). 参考:hibernate缓存管理 1.缓存概述 缓存(cache)在java应用程序中是一组内存中的集合示例,它保存着永久性存储源(如硬盘上的文件或数据库)中数据的备份,它的读写速度比读写硬盘的速度快。应用程序在运行时直接读写缓存中的数据,只在某些特定时刻按照缓存中的数据来同步更新数据存储源。如果缓存中存放的数据量非常大,也会用硬盘作为缓存的物理介质 缓存的作用就是降低应用程序直接读写永久性数据存储源的频率,从而增强应用的运行性能 缓存的实现不仅需要作为物理介质的硬件(内存),同时还需要用于管理缓存的并发访问和过期等策略的软件 2.缓存范围分类 缓存的范围决定了缓存的声明周期以及可以被谁访问。总共分三类 1)事务范围 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结束.事务范围的缓存使用内存作为存储介质,一级缓存就属于事务范围. 2)应用范围(也叫进程范围) 应用程序的缓存可以被应用范围内的所有事务共享访问.缓存的生命周期依赖于应用的生命周期,只有当应用结束时,缓存的生命周期才会结束.应用范围的缓存可以使用内存或硬盘作为存储介质,

hibernate如何实现延迟加载

hibernate 如何实现延迟加载 延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。在Hibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在Hibernate3中还提供了对属性的延迟加载。下面我们就分别介绍这些种类的延迟加载的细节。 A、实体对象的延迟加载: 如果想对实体对象使用延迟加载,必须要在实体的映射配置文件中进行相应的配置,如下所示: …… 通过将class的lazy属性设置为true,来开启实体的延迟加载特性。如果我们运行下面的代码: User user=(User)session.load(User.class,”1”);(1) System.out.println(user.getName());(2) 当运行到(1)处时,Hibernate并没有发起对数据的查询,如果我们此时

通过一些调试工具(比如JBuilder2005的Debug工具),观察此时user对象的内存快照,我们会惊奇的发现,此时返回的可能是User$EnhancerByCGLIB$$bede8986类型的对象,而且其属性为null,这是怎么回事?还记得前面我曾讲过session.load()方法,会返回实体对象的代理类对象,这里所返回的对象类型就是User对象的代理类对象。在Hibernate中通过使用CGLIB,来实现动态构造一个目标对象的代理类对象,并且在代理类对象中包含目标对象的所有属性和方法,而且所有属性均被赋值为null。通过调试器显示的内存快照,我们可以看出此时真正的User对象,是包含在代理对象的CGLIB$CALBACK_0.target属性中,当代码运行到(2)处时,此时调用user.getName()方法,这时通过CGLIB赋予的回调机制,实际上调用CGLIB$CALBACK_0.getName()方法,当调用该方法时,Hibernate会首先检查CGLIB$CALBACK_0.target属性是否为null,如果不为空,则调用目标对象的getName方法,如果为空,则会发起数据库查询,生成类似这样的SQL语句:select * from user where id=’1’;来查询数据,并构造目标对象,并且将它赋值到CGLIB$CALBACK_0.target属性中。 这样,通过一个中间代理对象,Hibernate实现了实体的延迟加载,只有当用户真正发起获得实体对象属性的动作时,才真正会发起数据库查询操作。所以实体的延迟加载是用通过中间代理类完成的,所以只有session.load()方法才会利用实体延迟加载,因为只有session.load()方法才会返回实体类的代理类对象。

hibernate框架必问的面试题

108.为什么要使用 hibernate? hibernate 是对 jdbc 的封装,大大简化了数据访问层的繁琐的重复性代码。 hibernate 是一个优秀的 ORM 实现,很多程度上简化了 DAO 层的编码功能。 可以很方便的进行数据库的移植工作。 提供了缓存机制,是程序执行更改的高效。 109.什么是 ORM 框架? ORM(Object Relation Mapping)对象关系映射,是把数据库中的关系数据映射成为程序中的对象。 使用 ORM 的优点:提高了开发效率降低了开发成本、开发更简单更对象化、可移植更强。 115.hibernate 中如何在控制台查看打印的 SQL 语句? 在 Config 里面把 hibernate. show_SQL 设置为 true 就可以。但不建议开启,开启之后会降低程序的运行效率。 116.hibernate 有几种查询方式? 三种:hql、原生 SQL、条件查询 Criteria。 117.hibernate 实体类可以被定义为 final 吗? 实体类可以定义为 final 类,但这样的话就不能使用 hibernate 代理模式下的延迟关联提供性能了,所以不建议定义实体类为 final。 118.在 hibernate 中使用 Integer 和 int 做映射有什么区别? Integer 类型为对象,它的值允许为 null,而 int 属于基础数据类型,值不能为 null。 119.hibernate 是如何工作的? 读取并解析配置文件。 读取并解析映射文件,创建 SessionFactory。 打开 Session。 创建事务。 进行持久化操作。 提交事务。 关闭 Session。 关闭 SessionFactory。 120.get()和 load()的区别? 数据查询时,没有 OID 指定的对象,get() 返回 null;load() 返回一个代理对象。 load()支持延迟加载;get() 不支持延迟加载。

北大青鸟Java培训班谈10个常见的java面试题

面试常常有,但成功面试又有几个呢,对于我们Java程序员来说,本就不善于表达,如何能在面试的时候成功呢。 在Java J2EE方面进行面试时,常被问起的Hibernate面试问题,大多都是针对基于Web的企业级应用开发者的角色的。 Hibernate框架在解决方案。 Hibernate将你从数据库相关的编码中解脱了出来,使你可以更加专注地利用强大的面向对象的设计原则来实现核心的业务逻辑。 采用Hibernate后,你就能够相当容易地在不同的数据库间进行切换,而且你还可以利用Hibernate提供的开箱即用的二级缓存以及查询缓存功能。 你也知道,大部分Java面试中所提的问题不仅仅会涉及Java的核心部分,而且还会涉及其它的Java框架,比如,根据项目的要求也有可能会问到Spring框架方面的问题或者Struts方面的问题。 如果你要参加的项目使用了Hibernate作为ORM解决方案,你就应该同时准备好回答Spring和Hibernate这两个框架方面的问题。好好看看JD或者职位说明,如果其中的任何地方出现了Hibernate这个词,就要准备好怎样来面对Hibernate 方面的问题。

本文给出了一个Hibernate面试问题列表,这些都是我从朋友以及同事那里搜集来的。Hibernate是一个非常流行的对象关系影射框架,熟悉Hibernate的优势所在以及Hibernate的Sesion API是搞定Hibernate面试之关键所在。 北大青鸟上海云登校区专家和大家一起学习一下: Hibernate中get和load有什么不同之处? 把get和load放到一起进行对比是Hibernate面试时最常问到的问题,这是因为只有正确理解get()和load()这二者后才有可能高效地使用Hibernate。get和load的最大区别是,如果在缓存中没有找到相应的对象,get将会直接访问数据库并返回一个完全初始化好的对象,而这个过程有可能会涉及到多个数据库调用;而load方法在缓存中没有发现对象的情况下,只会返回一个代理对象,只有在对象getId()之外的其它方法被调用时才会真正去访问数据库,这样就能在某些情况下大幅度提高性能。你也可以参考Hibernate中get和load的不同之处,此链接给出了更多的不同之处并对该问题进行了更细致的讨论。 Hibernate中save、persist和saveOrUpdate这三个方法的不同之处? 除了get和load,这又是另外一个经常出现的Hibernate面试问题。所有这三个方法,也就是save()、saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别。例如,save()只能INSERT记录,但是saveOrUpdate()可以进行记录的INSERT和UPDATE。还有,save()的返回值是一个Serializable对象,而persist()方法返回值为void。你还可以访问save、persist以及saveOrUpdate,找到它们所有的不同之处。 Hibernate中的SessionFactory有什么作用? SessionFactory是线程安全的吗? 这也是Hibernate框架的常见面试问题。顾名思义,SessionFactory就是一个用于创建Hibernate的Session对象的工厂。SessionFactory通常是在应用启动时创建好的,应用程序中的代码用它来获得Session对象。作为一个单个的数据存储,它也是线程安全的,所以多个线程可同时使用同一个SessionFactory。Java JEE应用一般只有一个SessionFactory,服务于客户请求的各线程都通过这个工厂来获得Hibernate的Session实例,这也是为什么SessionFactory接口的实现必须是线程安全的原因。还有,SessionFactory的内部状态包含着同对象关系影射有关的所有元数据,它是不可变的,一旦创建好后就不能对其进行修改了。 Hibernate中的命名SQL查询指的是什么?

hibernate练习题

hibernate练习题 1年。以下语句中创建条件对象的正确语句是radio A,条件c = query . CreateCriteria();标准c =查询。添加标准(); C、条件c =会话.创建条件(); D、条件c =会话创建条件(用户类); 2的正确结论。查询对象是选择大于 A的对象,List()方法返回总数据为0到大于 B的列表对象,uniqueResut()方法返回对象或对象数组。数据总量为0到1条数据 C,hql:selectusername from user model可以使用list()方法获取查询结果 D,hql:selectusername from user model可以使用uniqueResut()方法获取查询结果 3Hibernate实体对象生产规范不包括以下规则中的哪一个来选择A,构造方法 B声明没有公共参数,标识属性256 所有属性的getter和setter方法D,声明为最终类(最终修饰符) 4在HQL语句的参数查询中,执行以下代码。下列选项可以正确地为参数赋值:QUERY = S . CREATE QUERY(\ radio A,query.setParameter(1,B,query.setParameter(0,C,query.setString(0,Tom);整数(0,汤姆); 5关于Hibernate的瞬时对象状态是错误的。它是为具有OID的瞬时

状态的更多对象选择 A,B与会话对象相关联,具有瞬时状态的对象具有OID,C不与会话对象相关联,并且具有瞬时状态的对象不具有OID。与会话对象相关联的瞬时状态对象没有OID, 6相关的QBC查询短语与会话对象不相关联,以下语句是正确的:多选 A,限制。介于表示范围比较b,限制。eq表示相等比较 C,限制。le表示小于或等于比较d,限制。ge表示大于或等于比较7年,以下操作对一级缓存的影响被错误地描述为 | 1执行删除操作时,如果对象没有OID,将引发异常b。执行更新操作时,如果对象没有OID,将引发异常 C。执行更新操作时,如果一级缓存中已经存在相同的OID数据,将引发异常D。执行合并操作时,如果一级缓存中已存在相同的OID 数据,将引发异常 8,以下哪一项不是配置无线电 A,hibernate . connection . URL B,https://www.wendangku.net/doc/b02142383.html,ername C,Hibernate.show_sql D,hibernate . connection . password 9以下关于查询对象获取查询结果的语句不正确:无线电 A,List()方法uniqueriesce()方法返回对象或对象数组d,uniqueriesce()方法返回0到1条数据 10以下关于Hibernate缓存设置的描述是正确的:多选

技术架构选型方案报告

最高院执行项目 技术架构选型方案Fantasy 2011年8月25日

目录 总体架构!2整体系统描述 2架构选型!4 JDK选型(JDK1.6_22 32位) 4 IOC容器选型(Spring3.0.5.RELEASE) 5 ORM选型(MyBatis) 6 MVC选型(SpringMVC) 7认证和权限选型(shiro1.1 + ralasafe 1.1) 8前台组件选型 11案件导入导出架构设计!12总体架构设计 12客户端功能结构 13技术实现方式 14

总体架构 整体系统描述 系统架构图总揽 展示层 :主要面向B/S架构,展示层主要由web资源文件组成,包括JSP,JS 和大量的界面控件,同时还采用了AJAX和Flex等RIA技术,负责向用户展现丰富的界面信息,并执行用户的命令 控制层:负责展示层请求的转发、调度和基础验证,同时自动拦截后台返回 的Runtime异常信息。 领域层:是系统最为丰富的一层,主要负责处理整个系统的业务逻辑。这一 层包括业务服务和领域对象,同时负责系统的事务管理。其中业务服务可以提供本地调用和共享远程服务的功能。

数据访问控制层:数据访问层的目的很明确,主要作为提供数据持久化的功 能,包括数据的读取和写入,操作数据库的方法可以有两种方式ORM方式,ralasafe封装的方式。 公共基础设施层:可以包括Common通用模块,IOC模块,Logging日志模块, Exception异常模块和单元测试模块。

架构选型 1.JDK选型(JDK1.6_22 32位) JDK1.5、JDK1.6和JDK1.7选型 测试 1.增加5百万条String数据 测试 2.增加5百万数据到ArrayList中,并且插入时有额外的计算测试 3. HashMap 有5百万 keys, values. 每对key, value是通过并发线程计算 (这个测试主要测试计算和并发能力) 测试 4.把ArrayList长度位5百万的列表,插入1000个文件中,再从 1000个文件中读取放入到列表中。 (测试多核并发边缘) 从性能上看,JDK1.7 > JDK1.6 > JDK1.5

hibernate连接oracle数据库

一、Hibernate介绍 Hibernate是基于对象/关系映射(ORM,Object/Relational Mapping)的一个解决方案。ORM方案的思想是将对象模型表示的对象映射到关系型数据库中,或者反之。Hibernate 目前是ORM思想在Java中最成功、最强大的实现。它于2001年的年末发布第一个版本,立即引起了广泛的注意。2003年6月,Hibernate2发表,并且获得Jolt大奖,进而被JBoss 吸纳成为它的一个子项目。2005年3月,Hibernate 3发表,其中做了一些比较重大的改进。本文以Hibernate3为基础编写。 另外,Hibernate除了可以在J2EE容器中运行外,还可以运行在Java应用程序中。本文就是以Java应用程序为例来介绍它。 二、配置开发环境 本文以一个Java应用程序(Java Application)为例,介绍如何使用Hibernate来进行数据库操作。 在进行Hibernate开发之前,需要首先获得Hibernate类库、相应数据库的JDBC驱动类库。Hibernate类库可以从https://www.wendangku.net/doc/b02142383.html,中下载,目前的版本是3.0。而JDBC驱动可以根据不同的数据库来选择,在这个例子中,使用的是Oracle数据库,那么相应的JDBC驱动可以从Oracle安装目录\ora92\jdbc下获得。其他的数据库请根据相关的说明获得。 下载Hibernate包后,可以将它解压到一个文件夹,此处假设为C:\hibernate-3.0,然后将C:\hibernate-3.0\下的hibernate.jar和C:\hibernate-3.0\lib下的那些第三方类库也放到环境变量CLASSPATH中。(通常,只需要dom4j、cglig、commons-logging、commons-collections、log4j、ehcache、asm、jta、antlr这些类库就可以了) 做完这些配置后,就可以在此基础上进行基于Hibernate的Java程序开发了。 三、开发基于Hibernate的应用 现在假设我们在Oracle数据库中创建了一个表Student,它的字段如下表所示: 字段说明 Student_ID 学员编号,整型,PK,自动增长 Student_Name 学员姓名,字符串类型 Student_Age 学员年龄,整型 如果我们在Oracle中定义这个数据库表,我们可以定义一个创建数据库表的SQL脚本如下:create table Student(

Hibernate练习题

Hibernate练习题 1.一般情况下,关系数据模型与对象模型之间有哪些匹配关系(多选) A)表对应类 B)记录对应对象 C)表的字段对应类的属性 D)表之间的参考关系对应类之间的依赖关系 2.试述load()和get()的区别。 3.简述使用Hibernate完成持久化操作的3个准备和7个步骤。 4.在持久化层,对象分为哪些状态?(多选) A)临时状态 B)独立状态 C)游离状态 D)持久化状态 5.事务隔离级别是由谁实现的?(单选) A)Java应用程序 B)Hibernate C)数据库系统 D)JDBC驱动程序 6.假设对Customer类的orders集合采用延迟检索策略,编译或运行以下程序,会出现什么情况(单选) Session session=sessionFactory.openSession(); tx = session.beginTransaction(); Customer customer=(Customer)session.get(Customer.class,new Long(1)); https://www.wendangku.net/doc/b02142383.html,mit(); session.close(); Iterator orderIterator=customer.getOrders().iterator(); A)编译出错 B)编译通过,并正常运行 C)编译通过,但运行时抛出异常 7.以下程序代码对Customer的name属性修改了两次: tx = session.beginTransaction(); Customer customer=(Customer)session.load(Customer.class, new Long(1)); customer.setName(\"Jack\"); customer.setName(\"Mike\"); https://www.wendangku.net/doc/b02142383.html,mit(); 执行以上程序,Hibernate需要向数据库提交几条update语句?(单选)

hibernate源码分析 -- 持久化原理

hibernate源码分析-- 持久化原理 hibernate的持久化机制是采用session容器的方式来缓存数据,当进行save或者update对象时,Hibernate并未将这个对象实际的写入数据库中,而仅仅是在session缓存中根据应用的行为做了登记,在真正需要将缓存中的数据flush入数据库时才执行先前登记的所有行为。 这里执行就包括hibernate提出的二个概念VO,PO VO(Value Object)是独立的Java Object。 PO(Persistence Object)是由Hibernate纳入其实体容器(EntityMap)的对象,它代表了与数据库中某条记录对应的Hibernate实体,PO的变化在事务提交时将反应到实际数据库中。如果一个PO 与Session对应的实体容器中分离(如Session 关闭后的PO),那么此时,它又会变成一个VO。Hibernate到底是怎样运作的。 需要将所有缓存flush入数据库,Session启动一个事务,并按照insert,update,……,delete的顺序提交所有之前登记的操作(注意:所有insert执行完毕后才会执行update) Hibernate的flush处理机制,我们在一些复杂的对象更新和保存的过程中就要考虑数据库操作顺序的改变以及延时flush是否对程序的结果有影响。如果确实存在着影响,那就可以在需要保持这种操作顺序的位置加入flush强制Hibernate将缓存中记录的操作flush入数据库,这样看起来也许不太美观,但很有效。 通常我们使用Hibernate的时候,首先要通过以下的代码去创建一个Session. Configuration con=new Configuration().configure(); ServiceRegistry sr=new ServiceRegistryBuilder().applySettings(con.getProperties()).buildServiceRegis try(); SessionFactory factory=con.buildSessionFactory(sr); Session session=factory.openSession(); Transaction ts=session.beginTransaction();

ORM(ObjectRelational Mapper)---Hibernate对象映射

三、ORM(Object/Relational Mapper)---Hibernate对象映射 一. ORM(Object/Relational Mapper) 1. OR映射---Hibernate基本数据类型

2. OR映射---实体映射示例 *.hbm.xml, 主体内容包含表/类映射, id映射, 属性字段映射三个部分.示例文件:

XML文件头定义了文件的编码方式, DTD与Hibernate的版本有关, 上面是使用hibernate 3.x使用的DTD. 3. OR映射---表/类映射 name: 指定了Java数据封装的POJO类类型. table: 指定了数据库的表名 4. OR映射---id映射 name: 指定了映射POJO类的属性名, type: POJO类中属性的数据类型; column: 数据库表的主键字段; generator子元素:由其class属性指定主键生成方式: ?assigned: 主键由应用程序产生, 不需要hibernate干预 ?identity: 使用数据库的主键生成机制, 如MySQL, DB2、SQL Server的自增主键. ?sequence: 使用数据库的sequence机制, 如Oracle的sequence ?uuid.hex: 由Hibernate基于128位唯一值产生算法, 根据ip, 时间, jvm启动时间, 内部自增量生成十六进制的数值, 编码后成为一个32位长的字符串. 该方法提供了最 好的数据库插入性能和数据库平台适应性. ?uuid.string: 与uuid.hex类似, 只是生成的主键没有进行编码, 只有16位长度. 在某些数据库可能出错. ?hilo: 通过hilo算法实现主键生成, 需要额外的数据库表保存主键生成历史状态.

相关文档