学习笔记:映射——OneToOne

OneToOne

@OneToOne 一对一

private AddressEO address;
@OneToOne(cascade={CascadeType.All})
@JoinColumn(name="address_id")
public AddressEO getAddress(){
    return address;
}

@OneToOne定义的代码如下

@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 "";
  1. targetEntity 表示默认关联的实体类型,默认为当前标注的实体类型

    未设置与如下效果相同

    @OneToOne(TargetEntity=AddressEO.class)     //默认效果与该标注相同
    public AddressEO getAddress(){
        return address
    }
    
  2. cascade 表示与该实体一对一关联的联级别样式类型。默认将不关联任何操作

    @OneToOne(cascade={CascadeType.All})
    @JoinColumn(name="address_id")
    public AddressEO getAddress(){
        return address;
    }
    
  3. fetch 实体的加载方式,默认为即时加载EAGER,可以设置为惰性加载

    @OneToOne(fetch=FetchType.LAZY)     //默认效果为即时加载EAGER
    public AddressEO getAddress(){
        return address
    }
    

    tips:

    • FetchType.LAZY:懒(惰性)加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。

    • FetchType.EAGER:急(即时)加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。

    • 比方User类有两个属性,name跟address,就像百度知道,登录后用户名是需要显示出来的,此属性用到的几率极大,要马上到数据库查,用(EAGER)急加载;
      而用户地址大多数情况下不需要显示出来,只有在查看用户资料是才需要显示,需要用了才查数据库,用(LAZY)懒加载即可。

  4. optional 表示关联的属性能否为null,默认为true,表示可存在null值。如若设置为false。则该实体不能为null。并且要同时配合使用@JoinColumn标记。将保存实体关系的字段设置为唯一的不为null的并且不能更新的

    @OneToOne(Opttional=false)
    @JoinColum(name="address_id",unique=true,nullable=false,update=false)
    public AddressEO getAddress(){
        return address
    }
    
  5. mappedBy 用于双向关联实体时,标注在不保存关系的实体中

    @Entity
    @Table(name="address")
    public class AddressEO implements java.io.Serializable{
        private CustomerEO customer;
        @OneToOne(mappedBy="address")
        public CustomerEO getCustomer(){
            returm customer;
        }
        public void setCustomer(CustomerEO customer){
            this.customer=customer;
        }
    }
    

    详情见条目 Bidrectional 双向关联

@JoinColumn 关联指定列

  • @JoinColumn与@Column标记一样,用于注释表中的字段,并与Column有许多相同之处

    如name属性是用来标识所对应的字段的名称的。若customer表中存在字段addr_id,标识代码如下

    @OneToOne
    @JoinColumn(name="addr_id")
    public AddressEO getAddress(){
        return address
    }
    

    若此时,不设置name值,name取值遵循规则:

    name=关联表的名称+"_"+关联表字段的名称
    

    比如,CustomerEO实体中,如果不指定name值.默认将对应name=address_id;因为@JoinColumn注释在实体AddressEO属性上,实体AddressEO对应表明为"address";表address的主键是"id",所以此时对应的默认的字段名称为"address_id"

  • @JoinColumn与@Column区别为:@JoinColumn是保存表与表之间关系的字段,需要标注在实体属性上。@Column标注的是表中不包含表关系的字段。

  • 默认情况下,关联实体的主键一般作为外键,如果不希望主键作为外键,需设置referencedColumnName属性,如address表中增加一个字段"ref_id"。此时,通过customer表中的"address_id"字段关联的是address表中的"ref_id",而不是address表的主键.

    @OneToOne
    @JoinColumn(name="address_id",referencedColumnName="ref_id")
    public AddressEO getAddress(){
        return address
    }
    
  • @JoinColumn标记对@ManyToOne或@ManyToMany标记都能同时使用,它们所表示的含义不同?

Bidrectional 双向关联

  • 双向关联代码如下

    @Entity
    @Table(name="address")
    public class AddressEO implements java.io.Serializable{
        private CustomerEO customer;
        @OneToOne(mappedBy="address")
        public CustomerEO getCustomer(){
            returm customer;
        }
        public void setCustomer(CustomerEO customer){
            this.customer=customer;
        }
    }
    

    address作为CustomerEO实体中的属性存在, 如下代码所示

    @Entity
    @Table(name="Address")
    public class CustomerEO implements java.io.Serializable{
    private Address address;    //address作为CustomerEO实体种的属性存在
    @OneToOne(cascade={CascadeType.All})
    @JoinColumn(name="address_id")
    public AddressEO getAddress(){
        return address;
      }
    }
    

    这样配置后两者可以互相获得彼此的实体

    //通过CustomerEO获得AddressEO
    Integer custId=new Integer(1);
    CustomerEO customer=entityManager.find(Customer.class,custId);
    AddressEO address=customer.getAddress();
    //通过AddressEO获得CustomerEO
    Integer addrId=new Integer(1);
    AddressEO address=entityManager.find(AddressEO.class,addrId);
    CustomerEO customer=address.getCustomer();
    

@PrimaryKeyJoinColumn 主键关联

  • 一对一关系的表,可以使用另一种策略来保存表与表之间的关系--主键关联.主键关联是通过两个表种的主键来关联

    @Entity
    @Table(name="customer")
    public class CustomerEO implements java.io.Serializable{
        private AddressEO address;
        @OneToOne(cascade={CascadeType.ALL})
        @PrimaryKeyJoinColumn   //主键关联
        public AddressEO getAddress(){
            returm address;
        }
        public void setAddress(AddressEO address){
            this.address=address;
        }
    }
    

    若AddressEO与CustomerEO双向关联,则应该修改AddressEO的代码如下:

    @Entity
    @Table(name="Address")
    public class  AddressEO implements java.io.Serializable{
    private Address address;    
    @OneToOne
    @PrimaryKeyJoinColumn    //主键关联,双向关联
    public CustomerEO getCustomer(){
            returm customer;
        }
    public void setCustomer(CustomerEO customer){
            this.customer=customer;
        }
    }
    
  • 其属性与@JoinColumn属性类似

  • name属性标识所在实体的表中关联字段的名称

  • referencedColumnName 属性标识为所关联的表中字段名称

  • 同样@PrimaryColumnKey标记对@ManyToOne或@ManyToMany标记都能同时使用,它们所表示的含义不同?

默认关联

  • 如果表中使用了外键关联(Foreign Key),映射实体时无需做其他设置,实体管理器将默认映射外键所定义的两个表.

    例如,使用后如下语句创建表customer和表address

    --客户表
    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_increment,
    province varchar (50),
    city varchar (50),
    postcode varchar (50),
    detail varchar (50),
    PRIMARY KEY (id)
    )
    --创建外键
    ALTER TABLE customer ADD CONSTRAINT fk_customer_address
    FOREIGN KEY (address_id) REPERENCES address(id) ,
    
  • CustomerEO中的映射可以简化为如下所示代码

    @Entity
    @Table (name ="customer")
    public class CustomerEO implements java.io.Serializable {
    ...
    private AddressEO address;
    @OneToOne
    public AddressEO getAddress(){
    return address;
    }
    public void setAddress (AddressEO address){
        this.address=address;
    }
    
  • 使用外键利用的是数据库的底层机制,有利于数据的完整性.但使用外键减少了数据的灵活性.尤其在数据库分开部署时.最好不要采用外键的方式.所以是否采用外键进行实体间关系的映射要视具体情况而定.

一对一映射的考虑方向

  1. 考虑表结构的设计

    • 使用外键关联,考虑默认的实体关系映射
    • 使用主键关联,配合@PrimaryKeyJoinColumn注释使用
    • 使用字段关联,配合@JoinColumn注释使用
  2. 考虑实体关系的方向性

    • 若为双向关联,则在保存实体关系的实体中,要配合使用@JoinColumn注释;在没有保存实体关系的实体中,要使用mappedBy属性明确所关联的实体。

      例如,CustomerEO 实体AddressEO实体的关系保存在表“customer" 中,所以在CustomerEO实体中使用@JoinColumn,在AddressEO中设置mappedBy属性。


posted @ 2020-05-14 11:10  叄更灯火  阅读(514)  评论(0)    收藏  举报