ORM——数据库表与Java对象映射原理

来源:互联网 发布:腾讯软件管理官方下载 编辑:程序博客网 时间:2024/05/08 13:40

github实例参考:hibernate各种映射实例——XML、annotation
定义:

  • ORM(Object Relation Mapping):利用描述对象和数据库之间映射的元数据,自动且透明地把Java应用程序中的对象持久化到关系数据库中的表。

对象、关系范式的不匹配

  • 关联表示的区别:面向对象语言利用对象引用(object reference一对一、一对多、多对一、多对多);关系领域中使用外键(foreign key 一对多或一对一)表示。

  • 访问数据的区别:面向对象语言利用引用,从一个对象过渡到另一个对象,如同对象遍历一样访问数据;关系领域通过表的联结来访问数据。

  • 映射粒度:细粒度意味着类比表多

  • 继承、多态在数据库中无法直接表示

映射概念和策略

领域模型与元数据

  • 实现领域模型POJO类

  • ORM元数据(XML、注解):类、表、属性、列、关联、外键、Java类型与SQL类型映射等

// 常用注解- @GeneratedValue(strategy=GenerationType,generator="") - 可选,用于定义主键生成策略。Strategy - 表示主键生成策略,取值有: - GenerationType.AUTO - 根据底层数据库自动选择(默认),若数据库支持自动增长类型,则为自动增长。 - GenerationType.IDENTITY - 根据数据库的Identity字段生成,支持DB2、MySQL、MS、SQL Server、SyBase与HyperanoicSQL数据库的Identity类型主键。 - GenerationType.SEQUENCE - 使用Sequence来决定主键的取值,适合Oracle、DB2等支持Sequence的数据库,一般结合@SequenceGenerator使用。(Oracle没有自动增长类型,只能用Sequence) - GenerationType.TABLE  - 使用指定表来决定主键取值,结合@TableGenerator使用。-  @Column(name=attribute,nullable=true,unique=false,length=256,insertable=true,updateable=true,columnDefinition="Date=>DATE,TIME,TIMESTAMP or String=>VARCHAR,BLOB,TEXT")

映射持久化类

定义(重要):

  • 实体类型的对象:对应数据库中的一张表(具有主键值);对实体对象的引用被持久化为数据库中的引用(一个外键);实体对象具有自己的生命周期。
  • 值类型的对象:没有对应的表,做为实体对象的组件(属性);不支持引用,对于相同的值对象,每个实体对象都有自己的值对象实例;并且它的持久化被嵌入到自身实体的表行中。常见的值类型为Java的基本类型,另外再加上自定义的值类型类。
    例子:实体类型(User、BillingDetails)、值类型(Address)
    这里写图片描述

  • 类映射选项

  • 基础的属性和值类型组件映射<component>

继承和定制类型

InheritanceType:Hibernate提供3种方式
@ 每个类一张表——TABLE PER CLASS
@ 每个子类一张表——JOINED
@ 每个类层次结构一张表——SINGLE TABLE

  • 每个带隐式多态的具体类一张表:

    • 1、不支持多态关联,因为关联在数据库中被表示为外键约束,对于User与BillingDetails的One2Manny关系无法通过一个外键引用两张表。
    • 2、不同表的不同列具有完全相同的语义,使得数据库范式变得复杂,对于基类属性的改变会影响到子类属性。
    • 3、适用于类层次结构的最顶层,最顶层通常不需要多态。
      图【1】
      <generator class="native" />
  • 每个带有联合的具体类一张表——每个类一张表(TABLE_PER_CLASS)

    • 共享父类的属性
@Entity@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) //父类配置public abstract class BillingDetails {}@Entity@Table(name="CREDIT_CARD")public class CreditCard extends BillingDetails {}
  • 每个类层次结构一张表(SINGLE_TABLE)
    • 1、它是表示多态的最佳方式——多态和非多态的查询都执行得横好,并且更易于手工实现。schema也很简单。
    • 2、子类生成的属性列必须声明为空。
    • 3、创建了非键列之间的功能依赖,违背了第三范式。
      图【3】
@Entity@Inheritance(strategy=InheritanceType.SINGLE_TABLE)  //父类配置@DiscriminatorColumn(    name="discriminator",    discriminatorType=DiscriminatorType.STRING)public abstract class BillingDetails {}@Entity@DiscriminatorValue("CC")public class CreditCard extends BillingDetails {}
  • 每个子类一张表:把继承关系表示为相关的外键关联(JOINED)
    • 1、表继承关系表示为相关的外键,声明持久性属性的每个类、子类(抽象、接口)都有自己的表。
      图【4】
@Entity@Inheritance(strategy=InheritanceType.JOINED)public abstract class BillingDetails {}@Entity@PrimaryKeyJoinColumn(name="CREDIT_CARD_ID")public class extends BillingDetails {}//
  • 混合继承策略:把一个类层次结构映射到单张表,但是对于特定的子类,则通过外键映射策略切换到单独的表,就像使用每一个子类一张表一样。
    图【5】

映射集合和实体关联

  • 值类型的set、bag、list、map和组件集合映射(值类型的类——<composite-element>``<component>

  • ManyToOne——双向关联
    图【ManyToOne】

图【manyToOne-table】

public class Bid {  @ManyToOne  @JoinColum(name="ITEM_ID", nullable=false)  private Item item;}public class Item {  @OneToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE}, mappedby="item")  private Set<Bid> bids= new HashSet<Bid>();}// 1、双向关联——mappedby:把Bid的item端做的变化传播到数据库中。/* 1.1、在运行时,同一个外键值有两个不同的内存表示,Bid的item属性和由Item保存的bids集合的一个元素。当应用程序修改关联时:Hibernate会检查到内存持久化实例的两次变化,这两者更新同一个外键列,从数据库的角度来看,只有一个值需要更新——BID的ITEM_ID列。*/bid.setItem(item);item.getBids().add(bid);// 1.2、通过`mappedby="item"`属性,显示告诉Hibernate把`Bid`端的item所做的变化传播到数据库中。bid.setItem(item);item.getBids().add(bid);// 2、级联操作——CascadeType:当Item持久化时,同时持久化Bid。// 2.1、没有CascadeTypeItem newItem = new Item();Bid newBid = new Bid();newItem.addBid(newBid);session.save(newItem);session.save(newBid);// 2.2、使用CascadeTypeItem newItem = new Item();Bid newBid = new Bid();newItem.addBid(newBid);session.save(newItem);
  • javax.persistence.CascadeType.cascade:设置级联方式
    • CascadeType.PERSIST(级联新建)
    • CascadeType.REMOVE(级联删除)
    • CascadeType.REFRESH(级联刷新)
    • CascadeType.MERGE(级联更新)
    • CascadeType.ALL(全部四项)
  • fetch - 配置加载方式。取值有

    • Fetch.EAGER - 及时加载,多对一默认是Fetch.EAGER
    • Fetch.LAZY - 延迟加载,一对多默认是Fetch.LAZY
  • OneToOne

  • ManyToMany:多对多关联始终可以表示为对中间类的两个多对一关联。

会话对象管理

  • 持久化管理器:Session、Query、Criteria、Transaction

  • 扩展持久化上下文:每个请求一个会话而不是每个操作一个会话。实现DAO的共享持久化上下文。

    • 通过Hibernate ThreadLocal Session传播
    • 通过JTA传播
  • 利用Hibernate的对话

    • 利用托管对象的对话。
    • 给会话扩展Session,也就是上面两种会话传播。
  • HQL类似于SQL:这两者的区别在于HQL使用类名称而不是表名称,使用属性名称而不是列名称。它可以理解继承——可使用超类、接口查询。

  • 对象获取

    • 导航对象图
    • 通过标识符获取
    • HQL
    • sql
1 0
原创粉丝点击