Hibernate3.6课程文档(二)_第1页
Hibernate3.6课程文档(二)_第2页
Hibernate3.6课程文档(二)_第3页
Hibernate3.6课程文档(二)_第4页
Hibernate3.6课程文档(二)_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1. Hibernate检索1.1. hibernate检索方式说明Hibernate 提供了以下几种检索对象的方式 导航对象图检索方式: 根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的 OID 来检索对象 HQL 检索方式: 使用面向对象的 HQL 查询语言 QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口. 本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句1.2. HQL 检索方式HQL(Hibernate Query Language)

2、是面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有如下功能: 在查询语句中设定各种查询条件 支持投影查询, 即仅检索出对象的部分属性 支持分页查询 支持连接查询 支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字 提供内置聚集函数, 如 sum(), min() 和 max() 能够调用 用户定义的 SQL 函数或标准的 SQL 函数 支持子查询 支持动态绑定参数HQL检索方式包括以下步骤: 通过 Session 的 createQuery() 方法创建一个 Query 对象, 它

3、包括一个 HQL 查询语句. HQL 查询语句中可以包含命名参数 动态绑定参数 调用 Query 的 list() 方法执行查询语句. 该方法返回 java.util.List 类型的查询结果, 在 List 集合中存放了符合查询条件的持久化对象. Qurey 接口支持方法链编程风格, 它的 setXxx() 方法返回自身实例, 而不是 void 类型HQL vs SQL: HQL 查询语句是面向对象的, Hibernate 负责解析 HQL 查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句. HQL 查询语句中的主体是域模型中的类及类的属性

4、 SQL 查询语句是与关系数据库绑定在一起的. SQL 查询语句中的主体是数据库表及表的字段. HQL的语法类似SQL语法。1.2.1. 绑定参数 Hibernate 的参数绑定机制依赖于 JDBC API 中的 PreparedStatement 的预定义 SQL 语句功能. HQL 的参数绑定由两种形式: 按参数名字绑定: 在 HQL 查询语句中定义命名参数, 命名参数以 “:” 开头. 按参数位置绑定: 在 HQL 查询语句中用 “?” 来定义参数位置 相关方法: setEntity(): 把参数与一个持久化类绑定 setParameter(): 绑定任意类型的参数. 该方法的第三个参数

5、显式指定 Hibernate 映射类型绑定参数的形式,按参数名称绑定hql 查询:Query query = session.createQuery(from Customer c where + =:custname and c.age=:custage);/第一个参数代表名字,第二个参数代表值query.setString(custname, Tom);query.setInteger(custage, 21);List list = query.list();绑定参数的形式,按参数位置绑定Query query = session.createQuery(from Custo

6、mer c where =? and c.age=?);query.setString(0,Tom);query.setInteger(1, 21);Query.list();1.2.2. 使用别名通过HQL检索一个类的实例时,如果查询语句的其他地方需要引用它,应该为这个类指定一个别名from Customer as c where =:custname as 可省略1.2.3. 排序 HQL 采用 ORDER BY 关键字对查询结果排序hql 查询:Query query = session.createQuery(from Customer c order by c

7、.id);QBC查询:Criteria criteria = session.createCriteria(Customer.class);criteria.addOrder(org.hibernate.criterion.Order.asc(“id);1.2.4. 分页查询: setFirstResult(int firstResult): 设定从哪一个对象开始检索, 参数 firstResult 表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. 默认情况下, Query 从查询结果中的第一个对象开始检索 setMaxResult(int maxResults): 设定一次最多

8、检索出的对象的数目. 在默认情况下, Query 和 Criteria 接口检索出查询结果中所有的对象1.2.5. 投影查询 投影查询: 查询结果仅包含实体的部分属性. 通过 SELECT 关键字实现. Query 的 list() 方法返回的集合中包含的是数组类型的元素, 每个对象数组代表查询结果的一条记录 可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录, 使程序代码能完全运用面向对象的语义来访问查询结果集. 可以通过 DISTINCT 关键字来保证查询结果不会返回重复元素from Customer c join c.orders o where o.orderNumber l

9、ike T%如果希望查询结果中只包含Customer对象,可使用以下形式:select c from Customer c join c.orders o where o.orderNumber like T%-Select关键字还能用于选择对象的部分属性session.createQuery(“select c.id,,o.orderNumber from Customer c join c.orders o where o.orderNumber like T%”)对应的sql语句为:select c.ID,c.NAME,o.ORDER_NUMBER from CUSTOMER

10、S c inner join ORDERS o on c.ID-=o.CUSTOMER_ID where o.ORDER_NUMBER likeT%-过滤重复元素createQuery(“select distinct from customer c”);/list集合中存放的对象数组,数组中存放的查询的部分属性Query query = session.createQuery(select c.id,,o.orderNumber + from Customer c join c.orders o where o.orderNumber like %NO1%);Lis

11、t list = query.list(); Iterator it = list.iterator();while (it.hasNext() Object pair=(Object)it.next();Integer id=(Integer)pair0;String name=(String)pair1;String orderNumber=(String)pair2;System.out.print(id + +name+ +orderNumber);System.out.println( );使用构造函数Query query = session.createQuery(select

12、new cn.itcast.CustomerRow(c.id,,o.orderNumber) + from Customer c join c.orders o where o.orderNumber like %NO1%);List list = query.list(); Iterator it = list.iterator();while (it.hasNext() CustomerRow cr=(CustomerRow)it.next();System.out.print(cr.getId() + +cr.getName()+ +cr.getOrderNumber();S

13、ystem.out.println( );1.2.6. 分组与聚集函数报表查询用于对数据分组和统计, 与 SQL 一样, HQL 利用 GROUP BY 关键字对数据分组, 用 HAVING 关键字对分组数据设定约束条件.List list=session.createQuery(select ,count(c) from Customer c group by ).list();System.out.println(list.size();在 HQL 查询语句中可以调用以下聚集函数 count() min() max() sum() avg()使用聚集函数Query

14、query = session.createQuery(select count(*) from Customer c);/Integer count=(Integer)query.uniqueResult();/System.out.println(count +count); /*/Query query = session.createQuery(select avg(c.age) from Customer c);/ Float avg=(Float)query.uniqueResult();/ System.out.println(avg +avg);/*/ /Query query

15、 = session.createQuery(select max(c.age),min(c.age) from Customer c);/ Object maxmin=(Object)query.uniqueResult();/ System.out.println(max +(Long)maxmin0);/ System.out.println(min +(Long)maxmin1); /*/ /Query query = session.createQuery(select sum(c.age) from Customer c);/ Long sum=(Long)query.unique

16、Result();/ System.out.println(sum +sum);1.2.7. 在映射文件中定义命名查询语句 . -query = session.getNamedQuery(“findCustomersByName”);query.setString(“name”,”Tom”);query.list();1.2.8. 其他的查询动态查询:session.createCriteria(Customer.class) .add(Expression.like(“name”,name.toLowerCase(),MatchMode.ANYWHERE) .add(Expression.

17、eq(“age”,new Integer(11);集合过滤:hql:createQuery(“from Order o where o.customer=:customer and o.price100 order by o.price”).setEntity(“customer”,customer).list();使用集合过滤:session.createFilter(customer.getOrders(),”where this.price 100 order by this.price”).list();子查询:from Customer c where 1 Restrictions.

18、ge大于等于=Restrictions.lt小于Restrictions.le小于等于=Restrictions.between对应sql的between子句Restrictions.like对应sql的like子句Restrictions.in对应sql的in子句Restrictions.andand 关系Restrictions.oror关系Restrictions.sqlRestrictionSql限定查询1.4. 本地 SQL 检索方式(了解)SQLQuery sqlquery = session .createSQLQuery(select c.* from CUSTOMERS c

19、where+ like :customerName and c.age=:customerAge);/ 动态绑定参数sqlquery.setString(customerName, “%t%);sqlquery.setLong(customerAge, 21);“c”用来引用数据表的别名,例如以上代码中c.*表示使用c来作为customers表别名。 把sql查询返回的关系数据映射为对象sqlquery.addEntity(c, Customer.class);/ 执行sql select语句,返回查询结果。List list = sqlquery.list();1.5. 简单的

20、查询/使用hql查询 Query query=session.createQuery(from Customer c where = tom1 ); List list=query.list();/使用qbc查询 主要由Criteria、Criterion接口和Restrictions类组成,他支持在运行时动态生成查询语句。Criteria criteria=session.createCriteria(Customer.class); /设定查询条件,每个Criterion实例代表一个查询条件Criterion cn1=Restrictions.eq(name, tom1);c

21、riteria.add(cn1);list=criteria.list();/方法链编程:session.createCriteria(Customer.class) .add(Restrictions.eq(name, tom1) .list();1.6. HQL和QBC支持的各种运算运算类型HQL运算符QBC运算方法比较运算=Restrictions.eq()Restrictions.not(Restrictions.eq()=Restrictions.ge()Restrictions.lt()=Restrictions.le()is nullRestrictions.isNull()is

22、 not nullRestrictions.isNotNull()范围运算符inRestrictions.in()not inRestrictions.not(Restrictions.in()betweenRestrictions.between()not betweenRestrictions.not(Restrictions.between()字符串模式匹配likeRestrictionsion.like()逻辑andRestrictionsion.and()|Restrictionsion.conjunction()orRestrictionsion.or()|Restrictions

23、ion.disjunction()notRestrictionsion.not()1.6.1. 小结比较方面HQL检索QBC检索可读性优点:和sql相近,易读将语句肢解成一组criteria,较差功能支持各种查询不支持报表查询和子查询。有限的连接查询查询语句形式基于字符串形式的sql更加面向对象何时被解析运行时被解析编译时被解析,更易排错可扩展性不具扩展性用户可扩展criteria接口对动态查询语句的支持支持动态查询,编程麻烦适合动态生成查询语句2. 事务事务的概念事务可以看作是由对数据库的若干操作组成的一个单元,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求。事务的一个典型例子

24、是银 行中的转帐操作,帐户A把一定数量的款项转到帐户B上,这个操作包括两个步骤,一个是从帐户A上把存款减去一定数量,二是在帐户B上把存款加上相同的数 量。这两个步骤显然要么都完成,要么都取消,否则银行就会受损失。显然,这个转帐操作中的两个步骤就构成一个事务。数据库中的事务还有如下ACID特征。ACID分别是四个英文单词的首写字母,这四个英文单词是Atomicity、Consistency、Isolation、Durability,分别翻译为原子性、一致性、隔离性、持久性。原子性:指事务中的操作,或者都完成,或者都取消。一致性:指事务中的操作保证数据库中的数据不会出现逻辑上不一致的情况,一致性一

25、般会隐含的包括在其他属性之中。隔离性:指当前的事务与其他未完成的事务是隔离的。在不同的隔离级别下,事务的读取操作,可以得到的结果是不同的。持久性:指对事务发出COMMIT命令后,即使这时发生系统故障,事务的效果也被持久化了。与此相反的是,当在事务执行过程中,系统发生故障,则事务的操作都被回滚,即数据库回到事务开始之前的状态。对数据库中的数据修改都是在内存中完成的,这些修改的结果可能已经写到硬盘也可能没有写到硬盘,如果在操作过程中,发生断电或系统错误等故障, 数据库可以保证未结束的事务对数据库的数据修改结果即使已经写入磁盘,在下次数据库启动后也会被全部撤销;而对于结束的事务,即使其修改的结果还未

26、写入磁 盘,在数据库下次启动后会通过事务日志中的记录进行“重做”,即把丢失的数据修改结果重新生成,并写入磁盘,从而保证结束事务对数据修改的永久化。这样也 保证了事务中的操作要么全部完成,要么全部撤销。和并发2.1. 数据库的隔离级别在SQL92标准中,事务隔离级别分为四种,分别为:Read Uncommitted、Read Committed、Read Repeatable、Serializable,其中Read Uncommitted与Read Committed为语句级别的,而Read Repeatable与Serializable是针对事务级别的。在Oracle和SQL Server中设

27、置事务隔离级别的语句是相同的,都使用SQL92标准语法,即:Set Transaction Isolation Level Read Committed上面示例中的Read Committed可以被替换为其他三种隔离级别中的任意一种。在SQL Server中提供了所有这四种隔离级别。Read Uncommitted:一个会话可以读取其他事务未提交的更新结果,如果这个事务最后以回滚结束,这时的读取结果就可能是错误的,所以多数的数据库应用都不会使用这种隔离级别。Read Committed:这是SQL Server的缺省隔离级别,设置为这种隔离级别的事务只能读取其他事务已经提交的更新结果,否则,发

28、生等待,但是其他会话可以修改这个事务中被读取的记 录,而不必等待事务结束,显然,在这种隔离级别下,一个事务中的两个相同的读取操作,其结果可能不同。Read Repeatable:在一个事务中,如果在两次相同条件的读取操作之间没有添加记录的操作,也没有其他更新操作导致在这个查询条件下记录数增多,则两次 读取结果相同。换句话说,就是在一个事务中第一次读取的记录保证不会在这个事务期间发生改变。SQL Server是通过在整个事务期间给读取的记录加锁实现这种隔离级别的,这样,在这个事务结束前,其他会话不能修改事务中读取的记录,而只能等待事务结 束,但是SQL Server不会阻碍其他会话向表中添加记录

29、,也不阻碍其他会话修改其他记录。Serializable:在一个事务中,读取操作的结果是在这个事务开始之前其他事务就已经提交的记录,SQL Server通过在整个事务期间给表加锁实现这种隔离级别。在这种隔离级别下,对这个表的所有DML操作都是不允许的,即要等待事务结束,这样就保证了在 一个事务中的两次读取操作的结果肯定是相同的。 对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题: 脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.

30、 不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了. 幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行. 数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题. 一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱SQL ANSI

31、 SQL 标准定义了 4 种事务隔离级别,级别越高,成本越高:注: Oracle 只支持 2 种事务隔离级别:READ COMMITED, SERIALIZABLE. Oracle 默认的事务隔离级别为: READ COMMITED Mysql 支持4中事务隔离级别。Mysql 默认的事务隔离级别为: REPEATABLE READ2.2. 在 MySql 中设置隔离级别 每启动一个 mysql 程序, 就会获得一个单独的数据库连接. 每个数据库连接都有一个全局变量 tx_isolation, 表示当前的事务隔离级别. MySQL 默认的隔离级别为 Repeatable Read 查看当前的隔

32、离级别: 当前连接:SELECT tx_isolation; 全局:SELECT global.tx_isolation; 设置当前 mySQL 连接的隔离级别: set transaction isolation level read committed; 或set session transaction isolation level read uncommitted; 设置数据库系统的全局的隔离级别: set global transaction isolation level read committed;2.3. 在 Hibernate 中设置隔离级别JDBC 数据库连接使用数据库系

33、统默认的隔离级别. 在 Hibernate 的配置文件中可以显式的设置隔离级别. 每一个隔离级别都对应一个整数:隔离级别对应的整数表示READ UNCOMMITED1READ COMMITED2REPEATABLE READ4SERIALIZEABLE8Hibernate 通过为 Hibernate 映射文件指定 hibernate.connection.isolation 属性来设置事务的隔离级别。例:hibernate.connection.isolation = 4注意 Hibernate不可能改变在受管环境下由应用服务器提供的数据库连接的隔离级别,只能通过改变应用服务器配置的方式来改变

34、. 设置隔离级别是全局选项,会影响所有的连接和事务2.4. 管理session(CurrentSessionContext)2.4.1. 关于管理Session 尽管让程序自主管理 Session 对象的生命周期也是可行的, 但是在实际 Java 应用中, 把管理 Session 对象的生命周期交给 Hibernate 管理, 可以简化 Java 应用程序代码和软件架构 Hibernate 3 自身提供了三种管理 Session 对象的方法 Session 对象的生命周期与本地线程绑定 Session 对象的生命周期与 JTA 事务绑定 Hibernate 委托程序管理 Session 对象的

35、生命周期 在 Hibernate 的配置文件中, hibernate.current_session_context_class 属性用于指定 Session 管理方式, 可选值包括 thread: Session 对象的生命周期与本地线程绑定 jta*: Session 对象的生命周期与 JTA 事务绑定 managed: Hibernate 委托程序来管理 Session 对象的生命周期2.4.2. Session 对象的生命周期与本地线程绑定(通过Thread-local传播Session,线程本地化) 如果把 Hibernate 配置文件的 hibernate.current_sess

36、ion_context_class 属性值设为 thread, Hibernate 就会按照与本地线程绑定的方式来管理 Session Hibernate 按以下规则把 Session 与本地线程绑定 当一个线程(threadA)第一次调用 SessionFactory 对象的 getCurrentSession() 方法时, 该方法会创建一个新的 Session(sessionA) 对象, 把该对象与 threadA 绑定, 并将 sessionA 返回 当 threadA 再次调用 SessionFactory 对象的 getCurrentSession() 方法时, 该方法将返回 ses

37、sionA 对象 当 threadA 提交 sessionA 对象关联的事务时, Hibernate 会自动清理 sessionA 对象的缓存, 然后提交事务, 关闭 sessionA 对象. 当 threadA 撤销 sessionA 对象关联的事务时, 也会自动关闭 sessionA 对象 若 threadA 再次调用 SessionFactory 对象的 getCurrentSession() 方法时, 该方法会又创建一个新的 Session(sessionB) 对象, 把该对象与 threadA 绑定, 并将 sessionB 返回 配置: 在hibernate.cfg.xml文件中增

38、加 thread 不是调用sessionFactory.openSession().而是调用sessionFactory. getCurrentSession().获取session对象.从当前的线程提取session: 当前线程如果存在session对象,取出直接使用 当前线程如果不存在session对象,获取一个新的session对象和当前的线程绑定测试代码:3. 提升性能3.1. 使用连接池配置c3p0连接池* 引入c3p0-0.9.1.jar* 在hibernate.cfg.xml文件中增加如下配置org.hibernate.connection.C3P0ConnectionProvi

39、der 520120 30003.2. Hibernate的检索策略3.2.1. hibernate的检索策略简介检索策略的作用域可选的检索策略默认的检索策略运行时行为受影响的session的检索方法类级别立即延迟延迟load关联级别立即延迟迫切左外连接检索延迟loadget类级别和关联级别可选的检索策略及默认的检索策略3.2.2. 区分立即检索和延迟检索Class 标签中lazy=false 立即检索public void loadCustomerFalse()Session session=sessionFacoty.openSession();Transaction tx=session

40、.beginTransaction(); /该行代码让hibernate执行select语句,查询数据库Customer c=(Customer)session.load(Customer.class, 1);c.getAge();mit();session.close(); class 标签中lazy=true 延迟检索public void loadCustomerTrue() Session session=sessionFacoty.openSession(); Transaction tx=session.beginTransaction(); Customer c=(C

41、ustomer)session.load(Customer.class, 1); /该行代码让hibernate执行select语句, /查询数据库(需要用的时候查数据库) c.getAge(); mit(); session.close(); 3.2.3. 理解延迟检索中的代理public void loadCustomertrueProxy()Session session=sessionFacoty.openSession();Transaction tx=session.beginTransaction(); /此时查询到的c对象是一个代理对象Customer c=(Cus

42、tomer)session.load(Customer.class, 1);System.out.println(c.getClass().getName(); /代理对象c.getClass(); /hibernate不会执行select语句c.getId(); /hibernate不会执行select语句c.getAge(); /该行hibernate会执行select语句mit();session.close(); 只有延迟检索会产生代理对象,立即检索不会产生代理对象代理对象的类名如下所示:Hibernate使用javassist-3.9.0.GA.jar包创建代理。Cust

43、omer对象代理对象(初始化oid的值,其他的值不初始化)3.2.4. 初始化延迟检索中的代理/初始化代理对象public void loadCustomertrueProxyInit()Session session=sessionFacoty.openSession();Transaction tx=session.beginTransaction(); /此时查询到的c对象是一个代理对象Customer c=(Customer)session.load(Customer.class, 1);System.out.println(c.getClass(); /代理对象/判断代理对象是否被初

44、始化 对集合对象也适用if(!Hibernate.isInitialized(c) System.out.println(c.getClass(); /代理对象 System.out.println(没有被初始化); /初始化代理对象 hibernate执行select查询 Hibernate.initialize(c);mit();session.close(); 3.2.5. 区分类级别和关联级别的检索 类级别的检索: Customer c=(Customer)session.load(Customer.class, 1); session的方法直接检索Customer对象,对

45、Customer对象到底采用立即检索 还是延迟检索方式,是通过class元素的lazy属性设定的关联级别的检索: Customer c=(Customer)session.load(Customer.class, 1); Set set=c.getOrders()/检索Order对象的set集合 在这个例子中 session.load(Customer.class, 1):查询的主体表 c.getOrders():查询客体表 查询客体表是否发生,以何种方式发生(立即检索、延迟检索和迫切左外连接检索),就是关联级别检索 通过set元素lazy属性设定. 类级别检索策略 类级别可选的检索策略包括立即检索和延迟检索, 默认为延迟检索 类级别的检索策略可以通过 元素的 lazy 属性进行设置 如果程序加载一个对象的目的是为了访问它的属性, 可以采取立即检索. 如果程序加载一个持久化对象的目的是仅仅为了获得它的引用, 可以采用延迟检索 无论 元素的 lazy 属性是 true 还是 false, Session 的 get() 方法及 Query 的 list() 方法在类级别总是使用立即检索策略 若 元素的 lazy 属性为 true 或取默认值, Session 的 load() 方法不会执行查询数据表的 SELECT 语句, 仅返回代理类对象的实例,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论