对象对象/关系映射关系映射—Hibernate作者:钱安川( Moxie) Email:achqian@q学员要求学员要求:熟悉Java、SQL、JDBC,掌握面向对象的开发方法,并有实际项目开发经验q课程目标:课程目标:理解O/R Mapping原理,掌握Hibernate开发的相关知识,并能使用Hibernate进行实际项目开发1精品培训课件PPT目录目录一、持久化层-O/R Mapping二、Hibernate入门三、Hibernate映射申明(Mapping declaration)四、持久化对象的状态和生命周期五、Hibernate查询六、Hibernate最佳实践2精品培训课件PPT一、持久化层-一、持久化层-O/R Mapping基于B/S的典型三层架构如何分层?如何分层?q业务逻辑层和持久化层绝不要依赖于展现层q使用假设法测试例子:1、一个显示课程考试分数的列表现在要将不及格的分数用红色字体显示(低于60分)2、搜索3精品培训课件PPT如何进行对象-关系数据库的匹配如何进行对象-关系数据库的匹配public class User {private String name; private String password;private List address;………}create table tbl_user (name varchar(255) not null , password varchar(255),……….primary key (name))Ø 如何进行对象如何进行对象--关系数据库的匹配关系数据库的匹配??对象对象关系数据库关系数据库类的属性(基本类型)表的列类表1:n/n:1外键n:m关联表继承单表继承、具体表继承、类表继承4精品培训课件PPT对象对象—关系数据库的不匹配范式关系数据库的不匹配范式q粒度(granularity)的问题q子类型(subtypes)的问题q同一性(identity)的问题q与关联(associations)有关的问题q对象结构导航(navigation)的问题Ø范式不匹配的代价范式不匹配的代价q花费很多时间和精力来手工实现对象和关系的匹配。
q甚至要扭曲对象模型直到它与下层的关系技术匹配为止qJDBC API本身的问题JDBC和SQL提供了一个面向语句(即命令)的方法从SQL数据库中来回移动数据至少在三个时刻(Insert,Update,Select)必须指定一个结构化关系,这增加了设计和实现所需要的时间 5精品培训课件PPT基于关系数据库的持久层可选方案基于关系数据库的持久层可选方案优点优点缺点缺点SQL/JDBC成熟,流行,使用DAO模式代码烦杂,可读性差,维护困难,移植困难Entity BeanCMP(EJB1.1之后),未来的EJB3错误的设计不可移植,依赖性强,不可序列化,不支持多态的关联查询JDO简单、透明、标准不够成熟6精品培训课件PPT基于关系数据库的持久层可选方案基于关系数据库的持久层可选方案优点优点缺点缺点Apache OJB性能、稳定性,属于Apache 基金组织文档资源太少,支持标准太多成了负担(ODMG 3.0,JDO1.0)iBATIS可以控制更多的数据库操作细节实用于遗留系统的改造和对既有数据库的复用持久层封装不够彻底,只是一个DBHelperHibernate成熟、流行、功能强大并逐渐发展成Java 持久层事实上的标准。
不够透明7精品培训课件PPTO/R Mapping -What? Why?Ø什么是什么是O/R Mapping?对象-关系映射是一门非常实用的工程技术,它实现了Java应用中的对象到关系数据库中的表的自动的(和透明的)持久化,使用元数据(meta data)描述对象与数据库间的映射ØO/R Mapping的优点的优点q提高生产率(Productivity)q可维护性(Maintainability)q更好性能(Performance)q厂商独立性(Vendor independence)8精品培训课件PPT二、二、Hibernate入门入门ØHibernate概述概述 Hibernate是非常优秀、成熟的O/R Mapping框架它提供了强大的对象和关系数据库映射以及查询功能ØHibernate优势优势q开源(LGPL)q成熟q流行(约13 000 downloads/month)q自定义APIqJBoss 将用Hibernate3实现Entity Beans9精品培训课件PPTHibernate开发步骤开发步骤一、持久化类的设计一、持久化类的设计二、持久化类和关系数据库二、持久化类和关系数据库的映射的映射三、应用的开发三、应用的开发10精品培训课件PPT持久持久化化Java类必须遵循的原则类必须遵循的原则q为类的持久化类字段申明访问方法(get/set)。
Hibernate对JavaBeans风格的属性实行持久化q实现一个默认的构造方法(constructor)这样的话Hibernate就可以使用Constructor.newInstance()来实例化它们q如果是集合类型的属性,它的类型必须定义为集合的接口例如:List、Setq提供一个标识属性(identifier property)如果没有该属性,一些功能不起作用,比如:级联更新(Cascaded updates)Session.saveOrUpdate()11精品培训课件PPT持久化类和关系数据库的映射持久化类和关系数据库的映射XDoclet::它通过在Java源代码中加入特定的JavaDoc tag,从而为其添加特定的附加语义,之后通过XDoclet工具对代码中JavaDoc Tag进行分析,自动生成与代码对应的配置文件( 从数据库中已有的表结构中生成Hibernate映射文件当前版本是2.1可以去http://boss.bekk.no/boss/middlegen下载12精品培训课件PPTHibernate核心接口核心接口13精品培训课件PPTConfigurationØ概述:概述:Configuration 类负责管理Hibernate 的配置信息。
它包括如下内容:qHibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等qHibernate映射文件(*.hbm.xml)ØHibernate配置的两种方法:配置的两种方法:q属性文件(hibernate.properties)调用代码:Configuration cfg = new Configuration(); qXml文件(hibernate.cfg.xml)调用代码:Configuration cfg = new Configuration().configure();14精品培训课件PPTConfiguration-例子Ø数据库连接的配置数据库连接的配置hibernate.dialect net.sf.hibernate.dialect.MySQLDialecthibernate.connection.driver_class com.mysql.jdbc.Driverhibernate.connection.url jdbc:mysql://localhost/hibernatehibernate.connection.username roothibernate.connection.passwordØ数据库连接池的配置-数据库连接池的配置-DBCP((App Server连接池首选)连接池首选)hibernate.connection.provider_class net.sf.hibernate.connection.DBCPConnectionProvider配置配置DBCP连接池连接池Ø其它hibernate.show_sql truehibernate.jdbc.fetch_size 50hibernate.jdbc.batch_size 2515精品培训课件PPTSessionFactoryØ概述:概述:应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。
它在多个应用线程间进行共享通常情况下,整个应用只有唯一的一个会话工厂——例如在应用初始化时被创建然而,如果你使用Hibernate访问多个数据库,你需要对每一个数据库使用一个会话工厂 会话工厂缓存了生成的SQL语句和Hibernate在运行时使用的映射元数据Ø调用代码:调用代码:SessionFactory sessionFactory = cfg.buildSessionFactory();16精品培训课件PPTSession(会话会话)Ø概述:概述:qSession不是线程安全的,它代表与数据库之间的一次操作,它的概念介于Connection和Transaction之间q Session也称为持久化管理器,因为它是与持久化有关的操作接口q Session通过SessionFactory打开,在所有的工作完成后,需要关闭q它与Web层的HttpSession没有任何关系Ø调用代码调用代码Session session = sessionFactory.openSession();17精品培训课件PPTTransaction(事务事务)Ø概述:概述: 它将应用代码从底层的事务实现中抽象出来——这可能是一个JDBC事务,一个JTA用户事务或者甚至是一个公共对象请求代理结构(CORBA)——允许应用通过一组一致的API控制事务边界。
这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性Ø调用代码:调用代码: Transaction tx = session.beginTransaction();v注:注:使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认:autoCommit=false)18精品培训课件PPTQueryØ概述:概述:Query(查询)接口允许你在数据库上执行查询并控制查询如何执行查询语句使用HQL或者本地数据库的SQL方言编写Ø调用代码:调用代码:Query query = session.createQuery(“from User”); 19精品培训课件PPT用户的例子用户的例子持久化类-持久化类-User.javapublic class User { private Long id; private String name; private Date birthday; private String email; public User(){ } public User(String name,Date birthday,String email){ .....…Get/Set}映射文件-映射文件-User.hbm.xml 20精品培训课件PPT应用-应用-UserTest.javapublic 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 User("Jack",format.parse("1980-04-12"),"Jack@"); session.save(user); mit(); assertNotNull(user.getId()); session.clear(); User user_2 = (User)session.get(User.class,user.getId()); assertNotNull(user_2); session.close(); }21精品培训课件PPT应用-应用-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);22精品培训课件PPT三、三、Hibernate映射申明映射申明((Mapping declaration))hibernate-mapping一、类层次。
class1、主键id2、基本类型property3、自定义类many-to-one | one-to-one4、集合set | list | map | array4.1、one-to-many4.2、many-to-many5、子类subclass | joined-subclass6、其它component | any等二、查询语句Query说明:一个Hibernate-mapping中可以同时定义多个类Query非常简单,主要是用来放置查询语句,便于对数据库查询的统一管理和优化23精品培训课件PPThibernate-mapping(1)、schema(可选):数据库Schema Name(2)、default-cascade(可选,默认为none):默认的级联风格(3)、auto-import(可选,默认为true):是否在查询中只使用类名。
不用加package名字4)、package(可选),如果该映射文件中定义的类名不包含package,则使用这里定义的package作为类名的前缀24精品培训课件PPT一、类层次一、类层次class25精品培训课件PPT1、主键、主键-id(1)、name (可选) :标识属性的名称。
2)、type(可选):标识Hibernate类型的名字3)、column(可选-默认为属性名):对应数据库表的主键字段的名字4)、unsaved-value(可选-默认为null):这个值用来判断对象是否要保存 26精品培训课件PPT1.1主键生成策略主键生成策略generatorØgenerator主键生成器,每个主键都必须定义相应的主键生成策略它用来为持久化类实例生成唯一的标识ØHibernate内置的主键生成策略内置的主键生成策略q数据库提供的主键生成机制identity、sequence(序列) q外部程序提供的主键生成机制increment (递增) ,hilo(高低位) ,seqhilo(使用序列的高低位 ),uuid.hex(使用了IP地址+JVM的启动时间(精确到1/4秒)+系统时间+一个计数器值(在JVM中唯一) ),uuid.stringnative(本地),assigned(手工指定),foreign(外部引用)27精品培训课件PPT2、基本类型-、基本类型-property(4) update, insert (可选 - 默认为 true) :表明在用于UPDATE 和/或 INSERT的SQL语句中是否包含这个字段。
(5) formula (可选): 一个SQL表达式,定义了这个计算(computed) 属性的值计算属性没有和它对应的数据库字段28精品培训课件PPT3.1、、自定义类自定义类--many-to-one(3) class (可选 - 默认是通过反射得到属性类型): 关联的类的名字。
(4) cascade(级联) (可选): 指明哪些操作会从父对象级联到关联的对象 (5) outer-join(外连接) (可选 - 默认为 自动) hibernate.use_outer_join (7) property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外相对应29精品培训课件PPT例子例子:User-Group30精品培训课件PPT3.2、自定义类-one-to-oneØ一对一关联一对一关联:主键关联和惟一外键关联两种方式。
例子:User-IdCard(外键关联)31精品培训课件PPT4、集合-、集合-Set32精品培训课件PPT(1) name 集合属性的名称 (2) table (可选)目标关联数据库表(3) lazy (可选——默认为false)允许延迟加载(lazy initialization )(4) inverse (可选——默认为false) 标记有哪一方来维护关联关系(双向关联中使用)。
(5) cascade (可选——默认为none) 让操作级联到子实体 (6) order-by (可选, 仅用于jdk1.4) 指定表的字段(一个或几个)再加上asc或者desc(可选), 定义Map,Set和Bag的迭代顺序 (7) where (可选) 指定任意的SQL where条件(8) outer-join(可选-默认为auto)是否使用外联接33精品培训课件PPT4.1、、one-to-many Ø概念概念:一对多关联直接连接两个类对应的表,而没有中间集合表实现了一个一对多的关系模型,例如:User-Address)这里的Java集合必须满足下面的语义:qmap,set或list中不能包含null值q一个被包含的实体的实例只能被包含在一个集合的实例中(1) class(必须):被关联类的名称34精品培训课件PPT例子例子(one-to-many)::User-Address 35精品培训课件PPT4.2、many-to-many(1) column(必需): 中间映射表中,关联目标表的关联字段(2) class (必需): 类名,关联目标类(3) outer-join (可选 - 默认为auto) (1)(1) column(必需):当前表的关联字段36精品培训课件PPT例子例子(many to many)::student-trainClass37精品培训课件PPT5、继承、继承Ø继承实现的三中策略继承实现的三中策略q单表继承。
每棵类继承树使用一个表(table per class hierarchy) q具体表继承每个子类一个表(table per subclass) q类表继承每个具体类一个表(table per concrete class)(有一些限制)Ø单表继承单表继承38精品培训课件PPT例子例子(继承继承)::user-student39精品培训课件PPT双向关联双向关联Ø概念:概念:双向关联允许通过关联的任一端访问另外一端。
在Hibernate中, 支持两种类型的双向关联q一对多(one-to-many),Set或者bag值在一端, 单独值(非集合)在另外一端 q多对多(many-to-many),两端都是set或bag值40精品培训课件PPT例子例子(双向关联双向关联)::group-user 41精品培训课件PPT例子:从例子:从Java代码看代码看group-user双向关联双向关联的的inverseØ概念概念:inverse用来标识双向关联的关联关系由哪一端维护。
默认inverse的值为false,由主动方负责维护关联关系;如果设为true,则由反向一端维护关联关系Ø用例:用例:我们假设已经有一个Group类的实例:adminGroup,现在我们要新增一个用户,并且将用户分配到adminGroup中qinverse=“false”,由主动方Group负责维护group-user的关联关系.User user = new User(“Jak”);adminGroup.getUsers.add(user);session.save(user);session.update(group);qinverse=“true”,由Group的反向段User负责维护关联关系User user = new User(“Jak”);user .setGroup(adminGroup);session.save(user);42精品培训课件PPT四、持久化对象的状态四、持久化对象的状态Ø瞬时对象瞬时对象(Transient Objects)::使用new 操作符初始化的对象不是立刻就持久的它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收。
Ø持久化对持久化对(Persist Objects)::持久实例是任何具有数据库标识的实例它有持久化管理器Session统一管理,持久实例是在事务中进行操作的——它们的状态在事务结束时同数据库进行同步当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中Ø离线对象离线对象(Detached Objects)::Session关闭之后,持久化对象就变为离线对象离线表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理43精品培训课件PPT持久化对象的生命周期(持久化对象的生命周期(lifecycle))44精品培训课件PPTHibernate脏数据字段捡入Ø检索一个用户,并将它的用户名更改为检索一个用户,并将它的用户名更改为“Mary”Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();User user = (User) session.get(User.class, userId);user.setName("Mary");mit();session.close();45精品培训课件PPT持久化对象必须唯一持久化对象必须唯一Ø一个一个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);46精品培训课件PPT五、五、Hibernate查询查询Ø概述:概述:数据查询与检索是Hibernate中的一个亮点相对其他ORM实现而言,Hibernate提供了灵活多样的查询机制q标准化对象查询标准化对象查询(Criteria Query):以对象的方式进行查询,将查询语句封装为对象操作优点:可读性好,符合Java 程序员的编码习惯缺点:不够成熟,不支持投影(projection)或统计函数(aggregation)qHibernate语言查询(语言查询(Hibernate Query Language,,HQL)):它是完全面向对象的查询语句,查询功能非常强大,具备继承、多态和关联等特性 Hibernate官方推荐使用HQL进行查询qNative SQL Queries((原生原生SQL查询)查询):直接使用数据库提供的SQL方言进行查询47精品培训课件PPT例子:标准化对象查询例子:标准化对象查询(Criteria Query)Ø简单例子:简单例子:查询用户名以“J”开头的所有用户Criteria criteria = session.createCriteria(User.class); criteria.add(Expression.like("name","J%")); List users = criteria.list();48精品培训课件PPTHibernate语言查询(语言查询(Hibernate Query Language,,HQL))ØHQL用面向对象的方式生成用面向对象的方式生成SQLq以类和属性来代替表和数据列q支持多态q支持各种关联q减少了SQL的冗余ØHQL支持所有的关系数据库操作支持所有的关系数据库操作q连接(joins,包括Inner/outer/full joins),笛卡尔积(cartesian products)q投影(projection)q聚合(Aggregation,max, avg)和分组(group)q排序(Ordering)q子查询(Subqueries)qSQL函数(SQL function calls)49精品培训课件PPT例子:例子: 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”组的所有用户Query query = session.createQuery(“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)50精品培训课件PPT六、六、Hibernate最佳实践(最佳实践(Best Practices))1、使用Configuration装载映射文件时,不要使用绝对路径装载。
最好的方式是通过getResourceAsStream()装载映射文件,这样Hibernate会从classpath中寻找已配置的映射文件2、SessionFactory的创建非常消耗资源,整个应用一般只要一个SessionFactory就够了,只有多个数据库的时候才会使用多个SessionFactory3、在整个应用中,Session和事务应该能够统一管理Spring为Hibernate提供了非常好的支持)4、将所有的集合属性配置设置为懒加载(lazy=”true”)在hibernate2.x版本中,lazy默认值是“false”,但hibernate3.x已经将lazy的默认改为“true”了51精品培训课件PPTHibernate最佳实践(最佳实践(Best Practices))5、在定义关联关系时,集合首选Set,如果集合中的实体存在重复,则选择List(在定义配置文件时,可以将List定义为bag),数组的性能最差6、在一对多的双向关联中,一般将集合的inverse属性设置为true,让集合的对方维护关联关系例如:Group-User,由User来维护Group和User的关联关系。
7、HQL子句本身大小写无关,但是其中出现的类名和属性名必须注意大小写区分8、在非分布式架构中,不需要使用DTO来向上层传输数据直接使用POJO的Entity就可以了9、如果要精通Hibernate,熟练掌握关系数据库理论和SQL是前提条件52精品培训课件PPTHibernate资源资源q官方网站:http://www.hibernate.orgq国内网站:qJava新视线论坛:http://forum.hibernate.orgq《Hibernate 中文开发指南》作者夏昕( 曹晓钢 唐勇(http://www.china- Hibernate in Action》 作 者 : Christian Bauer and Gavin King( A Developer's Notebook》作者:James Elliott 结束,谢谢结束,谢谢!53精品培训课件PPTThank You更多精品更多精品 敬请关注!敬请关注!。