zoukankan      html  css  js  c++  java
  • 实体关系映射

    一、实体关系概述    
        实体关系是指实体与实体之间的关系,从方向上分为单向关联和双向关联;从实体数量上分一对一,一对多和多对多。
    1、实体关系的方向性 
    (1)单向关联
        单向关联是一个实体中引用了另外一个实体。简单地说,就是通过一个实体可以获得另一个实体对象。
    例如,实体A对实体B的单向关联。
    实体A的代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class EntityA {<span style="font-family:Verdana;"></span> private EntityB entityB;
     
      public EntityB getEntityB() {
        return entityB;
      }
       
      public void setEntityB(EntityB entityB) {
        this.entityB = entityB;
      }
    }

    实体B的代码如下:

    1
    public class EntityB {}


    (2)双向关联
    此时实体A的代码不变,将实体B的代码修改为:

    1
    2
    3
    4
    public class EntityB {
      private EntityA entityA;
      //省略getter、setter方法
    }


    2、实体关系的数量性
    (1)一对一
      一对一是一个实体只能获得一个实体的引用,如上所述
    (2)一对多
      一个实体可以获得多个实体的引用,如:

    1
    2
    3
    4
    public class EntityA {
      private Collection<EntityB> entitys;
      // 省略getter、setter方法
    }


    (3)多对多
    此时实体A代码如一对多一样,而实体B代码改为:

    1
    2
    3
    4
    public class EntityB {
      private Collection<EntityA> entitys;
      // 省略getter、setter方法
    }


    二、一对一(@OneToOne)
      下面以客户实体(CustomerEO)与地址实体(AddressEO)为例
     1、单向关联
    假设一个客户对应一个地址,在数据库中表customer和表address定义的结构SQL语句如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    --客户表
    create table customer (
      id int(20) not null auto_increment,
      name varchar(100),
      address_id int(20),
      primary key (id)
    )
    --地址表
    create table address (
      id int(20) not null auto_increament,
      province varchar(50),
      city varchar(50),
      postcode varcahr(50),
      detail varchar(50),
      primary key (id)
    )

    此时将表customer映射为CustomerEO,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Entity
    @Table(name="customer")
    public class CustomerEO implements java.io.Serializable {
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Integer id;
     
      @OneToOne(cascade = { CascadeType.ALL })
      @JoinColumn(name = "address_id")
      private AddressEO address;
     
      。。。
    }

    将表address映射为AddressEO实体,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Entity
    @Table(name="address")
    public class AddressEO implements java.io.Serializable {
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Integer id;
       
      private String province;
      private String city;
      ...
      //省略getter、setter方法
    }


    现在来看看@OneToOne的定义:

    1
    2
    3
    4
    5
    6
    7
    8
    @Target({METHOD, FIELD}) @Retention(RUNTIME)
    public @interface OneToOne {
     Class targetEntity() default void.class;
     CascadeType[] cascade() default ();
     FetchType fetch() default EAGER;
     boolean optional() default true;
     String mappedBy() default "";
    }

    使用@OneToOne标记是,需要注意:
    a、targetEntity 属性表示默认关联的实体类型,默认为当前标注的实体类。
    b、cascade属性表示与此实体一对一关联的实体的级联样式类型。
    c、fetch属性是该实体的加载方式,默认为即时加载EAGER
    d、optional属性表示关联的该实体是否能够存在null值,默认为ture,如果设置为false,则该实体不能为null,并且要配合使用@JoinColumn标记,将实体关系关系设置为唯一的,不为null而且不能更新,代码如下:

    1
    2
    3
    @OneToOne(optional=false)
    @JoinColumn(name="address_id", unique=true, nullable=false, updatable=false)
    private AddressEo address;

    e、mappedBy属性用于酸性关联实体时,标注在不保存关系的实体中。后讲

    下面讲下@JoinColumn标记:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Target({METHOD, FIELD}) @Retention(RUNTIME)
    public @interface JoinColumn {
     String name() default "";
     String referencedColumnName() default "";
     boolean unique() default false;
     boolean nullable() default true;
     boolean insertable() default true;
     boolean updatable default true;
     String columnDefinition() default "";
     String table() default "";
    }


    使用@JoinColumn标记是,需要注意一下几点: 
    a、@JoinColumn与@Column标记一样,是用来注释表中的字段的,它的属性和@Column有很多相似之处,不在详述。 
    b、但是它们的区别在于:@JoinColumn注释是保存表与表之间关系的字段 
    c、如果不设置name,默认为name = 关联表的名称+"-"+关联表主键的字段名,在上面实例中,默认为“address_id” 
    e、默认情况下,关联的实体的主键一般是用来做外键的,但如果此时不想用主键作为外键,则需要设置referencedColumnName属性,例如: 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    create table address (
      id int(20) not null auto_increament,
      ref_id int(20) not null,
      province varchar(50),
      city varchar(50),
      postcode varcahr(50),
      detail varchar(50),
      primary key (id)
    )

    实体类中修改为:

    1
    2
    3
    @OneToOne
    @JoinColumn(name="address_id", referencedColumnName="ref_id")
    private AddressEO address;


    2、双向关联 
    前面只能通过实体CustomerEO对象来获得AddressEO对象,是单向关联,若在AddressEO中加入CustomerEO的引用,即为双向关联 
    双向关联后AddressEO实体的代码为: 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Entity
    @Table(name="address")
    public class AddressEO implements java.io.Serializable {
      ...
      @OneToOne(mappedBy="address")
      private CustomerEO customer;
      ...
      
      
    }

    其中mappedBy属性用来指明所映射的实体关系,它的值为所关联实体中该属性的名称,如在CustomerEO实体中address为它的属性存在。

    3、主键关联(@PrimaryKeyJoinColumn)
    在上面使用的字段关联,现在谈下主键关联,在两个表的结构中customer表中,去掉address_id字段,其他不变。但是实体类配置修改为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Entity
    @Table(name="customer")
    public class CustomerEO implements java.io.Serializable {
      ...
      @OneToOne(cascade = { CascadeType.ALL })
      @PrimaryKeyJoinColumn
      private AddressEO address;
      
      ...
    }
     
    @Entity
    @Table(name="address")
    public class AddressEO implements java.io.Serializable {
      ...
      @OneToOne
      @PrimaryKeyJoinColumn
      private CustomerEO customer;
       
      ...
     
    }

    @PrimarKeyJoinColumn注释定义如下:

    1
    2
    3
    4
    5
    6
    @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
    public @interface PrimaryKeyJoinColumn {
      String name() default "";
      String referencedColumnName() default "";
      String columnDefinition() default "";
    }


    4、默认关联 
    在建立customer和address后,加入外键约束如: 

    1
    2
    alter table customer add constraint fk_custommer_address
    foreign key (address_id) references address (id);

    则在实体类中只需要加@OneToOne标记即可

    注:使用外键利用的是数据库底层的机制,有利于数据的完整性。但是外键减少了数据的灵活性。

    5、最后,说下一对一映射的一般步骤:
    (1)第一步,确定实体与实体的关系,如果是一对一,则要使用@OneToOne注释
    (2)第二步,考虑表结构的设计。
      a、若使用外键关联,则考虑默认关联。
      b、若使用主键关联,则需要配合@PrimaryKeyColumn注释
      c、若使用字段关联,则需要配合@JoinColumn注释使用
    (3)第三部,考虑实体关系的方向性。

  • 相关阅读:
    事以密成,能者低调
    时间过得真快,一晃三年过去了
    读书随记2011111
    Makefile
    ubuntu 7 下 tftp 的配置
    uboot移植到nano2410
    ubuntu 7.04 Feisty Fawn 安装手记之五:安装常用软件
    移植linux2.6.18到arm9
    移植busybox 1.4.2
    UBoot中SMDK2410的NAND Flash驱动。
  • 原文地址:https://www.cnblogs.com/yudar/p/4249014.html
Copyright © 2011-2022 走看看