Presentation is loading. Please wait.

Presentation is loading. Please wait.

对象/关系映射—Hibernate Email:achqian@yahoo.com.cn.

Similar presentations


Presentation on theme: "对象/关系映射—Hibernate Email:achqian@yahoo.com.cn."— Presentation transcript:

1 对象/关系映射—Hibernate

2 课程目标: 理解O/R Mapping原理 掌握Hibernate开发的相关知识 能使用Hibernate进行实际项目开发

3 目录 一、持久化层-O/R Mapping 二、Hibernate入门
三、Hibernate映射申明(Mapping declaration) 四、持久化对象的状态和生命周期 五、Hibernate查询 六、Hibernate最佳实践

4 一、持久化层-O/R Mapping 表现层 业务逻辑层 逻辑层 对象持久化层 数据层

5 如何进行对象-关系数据库的匹配 Book -oid:int -name:String -publish:Date
-description:String Oid Publish Name description

6 基于关系数据库的持久层可选方案 优点 缺点 SQL/ JDBC 成熟,流行,使用DAO模式 代码烦杂,可读性差,维护困难,移植困难
Entity Bean CMP(EJB1.1之后),EJB3 错误的设计。不可移植,依赖性强,不可序列化,不支持多态的关联查询 JDO 简单、透明、标准 不够成熟

7 基于关系数据库的持久层可选方案 优点 缺点 Apache OJB 性能、稳定性,属于Apache 基金组织
文档资源太少,支持标准太多成了负担(ODMG 3.0,JDO1.0) iBATIS 可以控制更多的数据库操作细节。实用于遗留系统的改造和对既有数据库的 复用。 持久层封装不够彻底,只是一个DBHelper。 Hibernate 成熟、流行、功能强大。并逐渐发展成Java 持久层事实上的标准。 不够透明

8 O/R Mapping -What? Why? 什么是O/R Mapping? O/R Mapping的优点
对象-关系映射是一门非常实用的工程技术,它实现了Java应用中的对象到关系数据库中的表的自动的(和透明的)持久化,使用元数据(meta data)描述对象与数据库间的映射。 O/R Mapping的优点 提高生产率(Productivity) 可维护性(Maintainability) 更好性能(Performance) 厂商独立性(Vendor independence)

9 二、Hibernate入门 Hibernate概述 Hibernate优势
Hibernate是非常优秀、成熟的O/R Mapping框架。它提供了强大的对象和关系数据库映射以及查询功能。 Hibernate优势 开源(LGPL) 成熟 流行(约 downloads/month) 自定义API JBoss 将用Hibernate3实现Entity Beans

10 Hibernate开发步骤 一、持久化类的设计 二、持久化类和关系数据库的映射 三、应用的开发

11 持久化Java类必须遵循的原则 为类的持久化类字段申明访问方法(get/set)。Hibernate对JavaBeans风格的属性实行持久化。 实现一个默认的构造方法(constructor)。这样的话Hibernate就可以使用Constructor.newInstance()来实例化它们。 如果是集合类型的属性,它的类型必须定义为集合的接口。例如:List、Set。 提供一个标识属性(identifier property)。如果没有该属性,一些功能不起作用,比如:级联更新(Cascaded updates)Session.saveOrUpdate()。

12 持久化类和关系数据库的映射

13 Hibernate核心接口

14 Configuration 概述:Configuration 类负责管理Hibernate 的配置信息。它包括如下内容:
Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等。 Hibernate映射文件(*.hbm.xml)。 Hibernate配置的两种方法: 属性文件(hibernate.properties)。 调用代码:Configuration cfg = new Configuration(); Xml文件(hibernate.cfg.xml)。 调用代码:Configuration cfg = new Configuration().configure();

15 Configuration-例子 数据库连接的配置(用属性文件方式)
hibernate.dialect net.sf.hibernate.dialect.MySQLDialect hibernate.connection.driver_class com.mysql.jdbc.Driver hibernate.connection.url jdbc:mysql://localhost/hibernate hibernate.connection.username root hibernate.connection.password 数据库连接池的配置-DBCP(App Server连接池首选) hibernate.connection.provider_class net.sf.hibernate.connection.DBCPConnectionProvider 配置DBCP连接池 其它 hibernate.show_sql true hibernate.jdbc.fetch_size 50 hibernate.jdbc.batch_size 25

16 SessionFactory 概述:应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。它在多个应用线程间进行共享。通常情况下,整个应用只用一个会话工厂——例如在应用初始化时被创建。然而,如果你使用Hibernate访问多个数据库,你需要对每一个数据库使用一个会话工厂。 会话工厂缓存了生成的SQL语句和Hibernate在运行时使用的映射元数据。 调用代码: SessionFactory sessionFactory = configuration.buildSessionFactory();

17 Session(会话) 概述: Session不是线程安全的,它代表与数据库之间的一次操作,它的概念介于Connection和Transaction之间。 Session也称为持久化管理器,因为它是与持久化有关的操作接口。 Session通过SessionFactory打开,在所有的工作完成后,需要关闭。 它与Web层的HttpSession没有任何关系。 调用代码 Session session = sessionFactory.openSession();

18 Transaction(事务) 概述: 调用代码:
它将应用代码从底层的事务实现中抽象出来——这可能是一个JDBC事务,一个JTA用户事务或者甚至是一个公共对象请求代理结构(CORBA)——允许应用通过一组一致的API控制事务边界。这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性。 调用代码: Transaction tx = session.beginTransaction(); 注:使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认:autoCommit=false)。

19 Query 概述: Query(查询)接口允许你在数据库上执行查询并控制查询如何执行。查询语句使用HQL或者本地数据库的SQL方言编写。 调用代码: Query query = session.createQuery(“from User”);

20 用户的例子 映射文件-User.hbm.xml 持久化类-User.java <hibernate-mapping>
<class name="com.test.um.User" table="TBL_USER"> <id name="id" column="ID"> <generator class="native"/> </id> <property name="name" column="NAME"/> <property name="birthday" column="BIRTHDAY"/> <property name=" " column=" "/> </class> </hibernate-mapping> 持久化类-User.java public class User { private Long id; private String name; private Date birthday; private String ; public User(){ } public User(String name,Date birthday,String ){ .....…Get/Set

21 应用-UserTest.java public void testCreate() throws Exception{
Configuration cfg = new Configuration(); cfg.addURL(UserTest.class.getResource("/com/test/um/User.hbm.xml")); SessionFactory sessionFactory = cfg.buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd"); User user = new session.save(user); tx.commit(); assertNotNull(user.getId()); session.clear(); User user_2 = (User)session.get(User.class,user.getId()); assertNotNull(user_2); session.close(); }

22 应用-UserTest.java 保存用户:session.save(user); 修改用户:session.update(user);
保存或修改用户:session.saveOrUpdate(user); 删除用户:session.delete(user); 删除所有用户:session.delete(“from User ”); 查询用户名为“test”的用户: Query query = session.createQuery("from User where user.name = :name"); query.setParameter(“test",user.getName()); User findUser = (User) query.list().get(0);

23 三、Hibernate映射申明(Mapping declaration)
一、类层次。class 1、主键。id 2、基本类型。property 3、自定义类。many-to-one | one-to-one 4、集合。set | list | map | array 4.1、one-to-many 4.2、many-to-many 5、子类。subclass | joined-subclass 6、其它。component | any等 二、查询语句。Query 说明:一个Hibernate-mapping中可以同时定义多个类。Query非常简单,主要是用来放置查询语句,便于对数据库查询的统一管理和优化。

24 一、类层次class <class name="ClassName" (1) table="tableName" (2)
mutable="true|false" (3) dynamic-update="true|false" (4) dynamic-insert="true|false" (5) select-before-update="true|false" (6) where="arbitrary sql where condition" (7) persister="PersisterClass" (8) />

25 1、主键-id <id name="propertyName" (1) type="typename" (2)
column="column_name" (3) unsaved-value="any|none|null|id_value" (4) <generator class="generatorClass"/> </id> (1)、name (可选) :标识属性的名称。 (2)、type(可选):标识Hibernate类型的名字。 (3)、column(可选-默认为属性名):对应数据库表的主键字段的名字。 (4)、unsaved-value(可选-默认为null):这个值用来判断对象是否要保存。

26 1.1主键生成策略generator generator Hibernate内置的主键生成策略
主键生成器,每个主键都必须定义相应的主键生成策略。它用来为持久化类实例生成唯一的标识。 Hibernate内置的主键生成策略 数据库提供的主键生成机制。identity、sequence(序列) 。 外部程序提供的主键生成机制。increment (递增) ,hilo(高低位) ,seqhilo(使用序列的高低位 ),uuid.hex(使用了IP地址+JVM的启动时间(精确到1/4秒)+系统时间+一个计数器值(在JVM中唯一) ),uuid.string。 其它。native(本地),assigned(手工指定),foreign(外部引用)。

27 2、基本类型-property <property name="propertyName" (1)
column="column_name" (2) type="typename" (3) update="true|false" (4) insert="true|false" (4) formula="arbitrary SQL expression" (5) /> (4) update, insert (可选 - 默认为 true) :表明在用于UPDATE 和/或 INSERT的SQL语句中是否包含这个字段。 (5) formula (可选): 一个SQL表达式,定义了这个计算(computed) 属性的值。计算属性没有和它对应的数据库字段。

28 四、持久化对象的状态 瞬时对象(Transient Objects):使用new 操作符初始化的对象不是立刻就持久的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收。 持久化对(Persist Objects):持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的——它们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。 离线对象(Detached Objects):Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理。

29 持久化对象的生命周期(lifecycle)

30 持久化对象必须唯一 一个Session中不能同时存在两个ID相同的持久化对象
例如:id为userId的user_1对象已经存在Session中,这时如果Session中试图产生一个user_2对象!! Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); User user_1 = (User)session.get(User.class,userId); User user_2 = new User(userId,”Mary”); session.update(user_2); 最后将会产生异常:net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session 解决办法: 使用evict ()方法将user_1实例从session中去除。session.evict(user_1);

31 五、Hibernate查询 概述:数据查询与检索是Hibernate中的一个亮点。相对其他ORM实现而言,Hibernate提供了灵活多样的查询机制。 标准化对象查询(Criteria Query):以对象的方式进行查询,将查询语句封装为对象操作。优点:可读性好,符合Java 程序员的编码习惯。缺点:不够成熟,不支持投影(projection)或统计函数(aggregation) Hibernate语言查询(Hibernate Query Language,HQL):它是完全面向对象的查询语句,查询功能非常强大,具备继承、多态和关联等特性 。Hibernate官方推荐使用HQL进行查询。 Native SQL Queries(原生SQL查询):直接使用数据库提供的SQL方言进行查询。

32 例子:标准化对象查询(Criteria Query)
简单例子:查询用户名以“J”开头的所有用户。 Criteria criteria = session.createCriteria(User.class); criteria.add(Expression.like("name","J%")); List users = criteria.list();

33 Hibernate语言查询(Hibernate Query Language,HQL)
HQL用面向对象的方式生成SQL 以类和属性来代替表和数据列 支持多态 支持各种关联 减少了SQL的冗余 HQL支持所有的关系数据库操作 连接(joins,包括Inner/outer/full joins),笛卡尔积(cartesian products) 投影(projection) 聚合(Aggregation,max, avg)和分组(group) 排序(Ordering) 子查询(Subqueries) SQL函数(SQL function calls)

34 例子: Hibernate语言查询(Hibernate Query Language,HQL)
简单例子:查询用户名以“J”开头的所有用户。 Query query = session.createQuery( "from User user where user.name like 'J%'"); List users = query.list(); 复杂例子:从User和Group中查找属于“admin”组的所有用户。 “from User user where user.group.name=‘admin’”); 如果用传统的SQL则查询语句如下: select user.userId as userId, user.name as name, user.groupId as groupId, user.idCardId as idCardId from TBL_USER user, TBL_GROUP group where (group.groupName='admin' and user.groupId=group.groupId)

35 六、Hibernate最佳实践(Best Practices)
1、使用Configuration装载映射文件时,不要使用绝对路径装载。最好的方式是通过getResourceAsStream()装载映射文件,这样Hibernate会从classpath中寻找已配置的映射文件。 2、SessionFactory的创建非常消耗资源,整个应用一般只要一个SessionFactory就够了,只有多个数据库的时候才会使用多个SessionFactory。 3、在整个应用中,Session和事务应该能够统一管理。(Spring为Hibernate提供了非常好的支持) 4、将所有的集合属性配置设置为懒加载(lazy=”true”)。在hibernate2.x版本中,lazy默认值是“false”,但hibernate3.x已经将lazy的默认改为“true”了。

36 Hibernate最佳实践(Best Practices)
5、在定义关联关系时,集合首选Set,如果集合中的实体存在重复,则选择List(在定义配置文件时,可以将List定义为bag),数组的性能最差。 6、在一对多的双向关联中,一般将集合的inverse属性设置为true,让集合的对方维护关联关系。例如:Group-User,由User来维护Group和User的关联关系。 7、HQL子句本身大小写无关,但是其中出现的类名和属性名必须注意大小写区分。 8、在非分布式架构中,不需要使用DTO来向上层传输数据。直接使用POJO的Entity就可以了。 9、如果要精通Hibernate,熟练掌握关系数据库理论和SQL是前提条件。

37 Hibernate资源 官方网站:http://www.hibernate.org
国内网站: Java新视线论坛: 《Hibernate 中文开发指南》作者夏昕( 《深入浅出Hibernate》作者:夏昕 曹晓钢 唐勇 《Hibernate in Action》作者:Christian Bauer and Gavin King( 《Hibernate: A Developer's Notebook》作者:James Elliott


Download ppt "对象/关系映射—Hibernate Email:achqian@yahoo.com.cn."

Similar presentations


Ads by Google