Orm框架:
l Hibernate
l Ibatis
l Ejb
l JDO(Java Date Object)
l Toplink(收费)
l OJB
Hibernate:灵活的设计,优秀的性能,齐全的文档,风靡全球的应用。
Ejb:重量级,高花费,开发周期长,成本高,限制了广泛的使用。
Ibatis:apache的子项目,也可以叫做sql mapping技术。相对hibernate的面向对象而言Ibatis更具灵活,需要的代码量较大,相对hibernate(全自动化)而言有点像半自动化。
Hibernate实现ORM简介:
对象关系映射(ORM)
ORM(Object/Relation Mapping)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将Java程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。 虽然同时暗示者额外的执行开销;但是如果ORM作为一种中间件实现,则会有很多机会做优化,而这些在手写的持久层并不存在。更重要的是用于控制转换的元数据需要提供和管理;但是同样,这些花费要比维护手写的方案要少;而且就算是遵守ODMG (Object Data Management Group )规范的对象数据库依然需要类级别的元数据(Meta Data)。
Hibernate 工作原理:
启动Hibernate
1.构建Configuration实例,初始化该实例中的所有变量 Configuration cfg = new Configuration().configure(); 加载hibernate.cfg.xml文件至该实例内存
2.通过hibernate.xfg.xml文件中的mapping节点配置,加载hbm.xml文件至该实例内存利用上面创建的Configuration实例构建一个SessionFactory实例 SessionFactory sf = cfg.buildSessionFactory();
3.由上面得到的SessionFactory实例创建连接 Session s = sf.openSession();
4.由上面得到的Session实例创建事务操作接口Transaction的一个实例tx Transaction tx = s.beginTransaction();
5.通过Session接口提供的各种方法操作数据库的访问
6.提交数据库的操作结果 tx.commit();
7.关闭Session链接 s.close();
Hibernate的运行过程如下图:
映射:
一、基本数据类型映射:对Java的基本类型的映射,如int,char,long等。
在Hibernate的映射文件中的配置如:<property name="name" type=”string” />
二、集合映射: 如List、Set、Map的映射。
三、关联映射:
1、 单向关联:一端只知道另一端的存在,用一个例子来说:A类知道B类,但B类并不知道A类的存在。
a)单向一对多:如一个人对应多个地址,
它的语法是:<one-to-many class="从表类名" />
b)单向一对一:
一对一的关联可以基于主键关联,但基于主键关联的持久化类不能拥有自己的主键生成策略,它的主键由关联类负责生成。
用一个简单的例子来说:一个人对应一个地址。
语法:<one-to-one name=”从表类名” constrained=”true”/>
另外一种写法:
<many-to-one name="从表对象名" column="从表主键名 " unique-key="true" />
c)单向多对多:一个人可对应多个地址,一个地址也可以对应多个人。
语法:<many-tomany column=”从表主键名” class=”从表类名” />
d)单向多对一:多个人对应一个地址。
语法:<many-to-one name="从表对象名 " column="从表主键名"/>
2、双向关联:两端都知道对方的存在,如:A类知道B类,B类也知道A类。
双向关联有两个概念:
a)、inverse(反转):将自己的控制权交给对方控制,多在在one-to-many和many-to-many的集合定义中使用。
b). Cascade(级联):用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似的操作,常用的Cascade取值由:none,all,save-update,delete,Delete-orphan。
双向关联与单向关联的区别就在与双向是互知的。
双向一对一:一个人对应一个地址,
语法:在主表这一方: <one-to-one name=”从表类名” cascade=”all” />
从表方:
<many-to-one name=”主表类名” column=”主表主键名” unique-key=”true” />
双向一对多:一个人对应多个地址。
主表这方:
<set name="从表对象名" inverse="true" cascade="all">
<!--column用于指定外键列名-->
<key column="外键列名" not-null="true"/>
<!--映射关联类-->
<one-to-many class="从表类名 "/>
</set>
从表方:
<many-to-one name="主表对象名" column="主键"cascade="all" />
双向多对多:一个人可对应多个地址,一个地址也可以对应多个人。
双向多对多需要第三张表来连接。
主表方:
<set name="从表对象名" table="连接表名" cascade="all">
<key column="指定连接表中关联当前实体类的列名" not-null="true"/>
<many-to-many column="连接表中关联本实体的外键" class="从表类名 "/>
</set>
从表方:
<set name="主表对象名" inverse="true" table="连接表名 ">
<!--column="addressid"是连接表中关联本实体的外键-->
<key column="从表主键"/>
<many-to-many column="当前实体主键" class="当前的实体类名 "/>
</set>
四、组件映射:多用来表示对象的从属关系(组合,聚合)。
比如一个学生可能有姓名,年龄,性别,成绩等属性,其中成绩是另一个对象,又有科目,分数属性,这里就需要用组件映射来表是之间的关系。
语法:
<component name=”对象属性名” class=”对象类名” >
<property name=”所属类属性名” />![]()
<component/>
五、继承映射:
继承映射分为三种:
a)、单表继承:就是将多个类的信息存放在一张表中,通常继承多个类。单表继续需要一个<discriminator column=”字段名称” type=”类型”/>鉴别器。
子类使用<subclass>标签定义,如
<subclass name=”子类名” discriminator-value=”鉴别器(用于区分多个子类)” >
<property name=”子类字段名”/>
<subclass/>
b)、具体表继承:每个子类一个表。
它的语法:
<union-subclass name="子类名" table="子类表名">
<property name="子类中的字段" />
</union-subclass>
c)、类表继承:每个具体类一个表。
每个具体类一张表可以有两种方法:
1、 第一种方法是使用 <union-subclass>。如:
<union-subclass name="子类名"table="表名 ">
<property name="字段名"/>
</union-subclass>
这种方式的局限在于,如果一个属性在超类中做了映射,其字段名必须与所有子类 表中定义的相同。
2、 另一种可供选择的方法是采用隐式多态;隐式多态则采用每个具体类的 PO 独立建表的策略,在它的映射文件中将看不出任何的和接口、抽象类的关系,同时对于抽象类。
<class name="子类名" table="表名">
<id name="id">
<generator class="native"/>
</id>
<property name="字段"/>
</class>
对于这种映射策略而言,通常用<any>来实现到父类的多态关联映射。
如:<any name=”父类名” meta-type=”String”>
<meta-value value=”子类别名” class=”子类类名”/>
<column name=”父类字段” />
<any />
这种方法的缺陷在于,在Hibernate执行多态查询时无法生成带UNION的SQL语句。
对“每个具体类映射一张表”的映射策略而言,隐式多态的方式有一定的限制。而<union-subclass>映射的限制则没有那么严格。