• @OneToMany、@ManyToOne以及@ManyToMany讲解


    一、一对多(@OneToMany)
    1、单向一对多模型
    假设通过一个客户实体可以获得多个地址信息。
    对于一对多的实体关系而言,表结构有两种设计策略,分别是外键关联和表关联。
    (1) 映射策略---外键关联
    在数据库中表customer和表结构address定义,如下:

     1 create table customer (
     2   id int(20) not null auto_increment,
     3   name varchar(100),
     4   primary key(id)
     5 )
     6  
     7 create table address (
     8   id int(20) not null auto_increment,
     9   province varchar(50),
    10   city varchar(50),
    11   postcode varchar(50),
    12   detail varchar(50),
    13   customer_id int(20),
    14   primary key (id)
    15 )

    注意此时外键定义在多的一方,也就是address表中。

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

    1 @Entity
    2 @Table(name="customer")
    3 public class CustomerEO implements java.io.Serializable {
    4   @OneToMany(cascade={ CascadeType.ALL })
    5   @JoinColumn(name="customer_id")
    6   private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
    7  ...
    8 }

    注释@OneToMany的定义代码如下:

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

    使用时要注意一下几点问题: 
    a、targetEntity属性表示默认关联的实体类型。如果集合类中指定了具体类型了,不需要使用targetEntity.否则要指定targetEntity=AddressEO.class。 
    b、mappedBy属性用于标记当实体之间是双向时使用。 

    (2) 映射策略---表关联 
    在上面address表中去掉customer_id字段,在增加一个表ref_customer_address,如下: 

    1 --客户地址关系表
    2 create table ref_customer_address (
    3   customer_id int(20) not null,
    4   address_id int(20) not null unique
    5 )

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

     1 @Entity
     2 @Table(name = "customer")
     3 public class CustomerEO implements java.io.Serializable {
     4   ...
     5   @OneToMany(cascade = { CascadeType.ALL })
     6   @JoinTable(name="ref_customer_address",
     7            joinColumns={ @JoinColumn(name="customer_id",referencedColumnName="id")},
     8            inverseJoinColumns={@JoinColumn(name="address_id",referencedColumnName="id")})
     9   private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
    10   ...
    11 }

    表关联@JoinTable,定义如下:

    1 @Target({METHOD,FIELD}) 
    2 public @interface JoinTable {
    3   String name() default "";
    4   String catalog() default "";
    5   String schema() default "";
    6   JoinColumn[] joinColumns() default {};
    7   JoinColumn[] inverseJoinColumns() default {};
    8   UniqueConstraint[] uniqueConstraints default {};
    9 }

    其中:
    a、该标记和@Table相似,用于标注用于关联的表。
    b、name属性为连接两张表的表名。默认的表名为:“表名1”+“-”+“表名2”,上面例子默认的表名为customer_address。
    c、joinColumns属性表示,在保存关系中的表中,所保存关联的外键字段。
    d、inverseJoinColumns属性与joinColumns属性类似,不过它保存的是保存关系的另一个外键字段。

    (3) 默认关联
    在数据库底层为两张表添加约束,如下:

    1 create table customer_address (
    2   customer_id int(20) not null,
    3   address_id int(20) not null unique
    4 )
    5 alter table customer_address add constraint fk_ref_customer foreign key (customer_id) references customer (id);
    6  
    7 alter table customer_address add constraint fk_ref_address foreign key (address_id) references address (id);

    这样,在CustomerEO中只需要在标注@OneToMany即可!


    二、多对一@ManyToOne
    1、单向多对一模型。
    (1) 外键关联
    配置AddressEO实体如下:

     1 @Entity
     2 @Table(name="address")
     3 public class AddressEO implements java.io.Serializable {
     4      
     5   @ManyToOne(cascade = { CascadeType.ALL })
     6   @JoinColumn(name="customer_id")
     7   private CustomerEO customer;
     8      
     9   // ...
    10 }

    @ManyToOne定义如下:

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

    (2) 默认关联
    数据库脚本定义的相关字段的约束,创建外键后,直接使用@ManyToOne

    三、高级一对多和多对一映射
    即双向关联模型,确定了双向关联后,多的一方AddressEO不变使用@ManyToOne,而CustomerEO实体修改为:

    1 @Entity
    2 @Table(name="customer")
    3 public class CustomerEO {
    4      
    5   @OneToMany(mappedBy="customer")
    6   private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
    7      
    8   // ...
    9 }

    其中,@OneToMany标记中的mappedBy属性的值为AddressEO实体中所引用的CustomerEO实体的属性名。 

    四、多对多(@ManyToMany)
    和一对多类型,不在赘述。@ManyToMany标记的定义如下:

    1 @Target({METHOD, FIELD}) @Retention(RUNTIME)
    2 public @interface ManyToMany {
    3   Class targetEntity() default void.class;
    4   CascadeType[] cascade() default {};
    5   FetchType fecth() default LAZY;
    6   String mappedBy() default "";
    7 }

    五、最后,谈谈关于集合类的选择
    在映射关系中可以使用的集合类有Collection、Set、List和Map,下面看下如何选择。
    1、定义时使用接口,初始化使用具体的类。
    如Collection可以初始化为ArrayList或HashSet;
    Set可以初始化为HashSet;
    List可以初始化为ArrayList;
    Map可以初始化为HashMap.
    2、集合类的选择
    Collection类是Set和List的父类,在未确定使用Set或List时可使用;
    Set集合中对象不能重复,并且是无序的;
    List集合中的对象可以有重复,并且可以有排序;
    Map集合是带有key和value值的集合。

  • 相关阅读:
    hdoj 1305字典树水题之二
    nyoj 547 水池加水 priority_queue优先级队列初体验
    nyoj167 找奶牛病毒 “按位或”运算 递归
    HDOJ4525 吃鸡腿 腾讯马拉松(五)
    hdoj 4523 切蛋糕 腾讯马拉松 大数加法比较
    如何学好3D游戏引擎编程《转自3D游戏引擎网》
    priority_queue 优先级队列的基本应用和重载问题
    poj1611 传染病 并查集
    srand((unsigned)time(NULL))和rand()
    最近被一个windows mobile照相的问题给难住了
  • 原文地址:https://www.cnblogs.com/fashflying/p/5145912.html
Copyright © 2020-2023  润新知