学习笔记:映射——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 "";
-
targetEntity 表示默认关联的实体类型,默认为当前标注的实体类型
未设置与如下效果相同
@OneToOne(TargetEntity=AddressEO.class) //默认效果与该标注相同 public AddressEO getAddress(){ return address } -
cascade 表示与该实体一对一关联的联级别样式类型。默认将不关联任何操作
@OneToOne(cascade={CascadeType.All}) @JoinColumn(name="address_id") public AddressEO getAddress(){ return address; } -
fetch 实体的加载方式,默认为即时加载EAGER,可以设置为惰性加载
@OneToOne(fetch=FetchType.LAZY) //默认效果为即时加载EAGER public AddressEO getAddress(){ return address }tips:
-
FetchType.LAZY:懒(惰性)加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。
-
FetchType.EAGER:急(即时)加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。
-
比方User类有两个属性,name跟address,就像百度知道,登录后用户名是需要显示出来的,此属性用到的几率极大,要马上到数据库查,用(EAGER)急加载;
而用户地址大多数情况下不需要显示出来,只有在查看用户资料是才需要显示,需要用了才查数据库,用(LAZY)懒加载即可。
-
-
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 } -
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; } -
使用外键利用的是数据库的底层机制,有利于数据的完整性.但使用外键减少了数据的灵活性.尤其在数据库分开部署时.最好不要采用外键的方式.所以是否采用外键进行实体间关系的映射要视具体情况而定.
一对一映射的考虑方向
-
考虑表结构的设计
- 使用外键关联,考虑默认的实体关系映射
- 使用主键关联,配合@PrimaryKeyJoinColumn注释使用
- 使用字段关联,配合@JoinColumn注释使用
-
考虑实体关系的方向性
-
若为双向关联,则在保存实体关系的实体中,要配合使用@JoinColumn注释;在没有保存实体关系的实体中,要使用mappedBy属性明确所关联的实体。
例如,CustomerEO 实体AddressEO实体的关系保存在表“customer" 中,所以在CustomerEO实体中使用@JoinColumn,在AddressEO中设置mappedBy属性。
-
浙公网安备 33010602011771号