@JoinColumn

来源:互联网 发布:淘宝子账号登录密码 编辑:程序博客网 时间:2024/06/13 07:28

@OneToOne注释只能确定实体与实体的关系是一对一的关系,不能指定数据库表中的保存的关联字段。所以此时要结合@JoinColumn标记来指定保存实体关系的配置。
@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注释时,应注意以下几个问题。

l @JoinColumn与@Column标记一样,是用于注释表中的字段的。它的属性与@Column属性有很多相同之处,这里就不详细讲述。请读者参阅5.2.2小节中有关@Column属性的部分。

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

l 与@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”。

提示:此规则只适用于与@OneToOne标记同时使用时。若与@ManyToOne或@ManyToMany标记同时使用时,将遵循其他的规则。

l 默认情况下,关联的实体的主键一般是用来做外键的。但如果此时不想主键作为外键,则需要设置referencedColumnName属性。例如,将address表中增加一个字段“ref_id”,address表的建表SQL变为以下所示。

CREATE TABLE address (

id int(20) NOT NULL auto_increment,

ref_id int int(20) NOT NULL,

province varchar(50) ,

city varchar(50) ,

postcode varchar(50) ,

detail varchar(50) ,

PRIMARY KEY (id)

)

此时,通过customer表中的“address_id”字段关联的是address表中的“ref_id”,而“ref_id”并不是address表中的主键,则实体中标注如代码下所示。

@OneToOne

@JoinColumn(name = “address_id”,referencedColumnName=”ref_id”)

public AddressEO getAddress() {

     return address;

}

属性referencedColumnName标注的是所关联表中的字段名,若不指定则使用的所关联表的主键字段名作为外键。

l JoinColumn标记不仅能够与@OneToOne使用,也可以@ManyToOne或@ManyToMany标记同时使用,它们所表示的含义不同,这些内容将在下文详细讲述。

用法实例:
@ManyToOne(targetEntity = Staff.class)
@JoinColumn(name = “auditedStaffId”, referencedColumnName = “staffId”)
private Staff auditedStaff;// 审核人
ManyToOne指的是多对一的数据关系,many指的是本类.one指的是目标类.
targetEntity 指的是目标类,即要加入到本类的实体类
referencedColumnName 指的是以目标类的何种属性作为本类的外键,不设置的话默认是目标类的主键.
name 指的是目标类外键在本类存的名称,例如目标类的外键是staffId,他在目标类的列名是staffId,在本类的列名是auditedStaffId.
再说一下jsp的传值,页面name的属性直接设置为 auditedStaff点上Staff类里本身的属性.和以上的设置无关.

1.标准注解
a) @Entity 映射一个实体类

   @Table 指定关联的表b) @Id 映射OIDc) @GeneratedValue 指定OID的生成策略      @GeneratedValue的属性strategy指定生成策略,     IDENTITY(自增长方式,如mysql)     SEQUENCE  (序列方式,如oracle)    TABLE (表方式,该方式便于数据库移植,但效率不高,主键的值是从这个表中取得的。)    AUTO (自动方式,该方式会把主键生成交给JPA的实现者来决定,Hibernate会根据底层数据库选择合适的方    式,如果用这种方式,可以不写,默认如此)   例如:@GenericGenerator(name="uuid_s",strategy="uuid")d) @Version 映射版本号属性e) @Column 指定属性对应的列的信息f) @Temporal 指定日期时间的类型(TIMESTAMP,DATE,TIME)g) 简单属性可以不用注解。默认就是@Basich) @Transient 指定属性不需要映射i) 复杂属性:关联,继承,组件,联合主键,集合
  1. 映射多对一

    1) @ManyToOne

    2) 指定关联列@JoinColumn(name=”xxx_id”)

  2. 映射一对多

    1) @OneToMany 默认会使用连接表做一对多的关联

    2) 添加@JoinColumn(name=”xxx_id”)后,就会使用外键关联,而不使用连接表了。

  3. 映射双向一对多

    1) 在多端:

    @ManyToOne

    2) 在一端:

    @OneToMany(mappedBy=”多端的关联属性名”):—-升级后–> @OneToMany

    @JoinColumn(name=”外键名”)

  4. cascade属性: 指定级联操作的行为(可多选)

    CascadeType.PERSIST :调用JPA规范中的persist(),不适用于Hibernate的save()方法

    CascadeType.MERGE:调用JPA规范中merge()时,不适用于Hibernate的update()方法

    CascadeType.REMOVE:调用JPA规范中的remove()时,适用于Hibernate的delete()方法

    CascadeType.REFRESH:调用JPA规范中的refresh()时,适用于Hibernate的flush()方法

    CascadeType.ALL:JPA规范中的所有持久化方法。

  5. mappedBy属性:用在双向关联中,把关系的维护权反转

    跟hibernate XML映射中的property-ref一样。

  6. cascade属性和mappedBy用在一起时,一定要通过调用双方的set方法来建立关系。

  7. 双向一对一

    1) 基于外键

    a) 在主控方:@OneToOne

    b) 在被控方:@OneToOne(mappedBy=”对方的关联属性名”)

    2) 基于主键: JPA标准中没有提供共享主键生成问题的标准方法,使用Hibernate的扩展

    a) 在主控方:Car

    @Id

    @GeneratedValue(generator=”my-uuid”)

    @GenericGenerator(name=”my-uuid”, strategy=”uuid”)

    private String id;

    @OneToOne(cascade={CascadeType.ALL})

    @PrimaryKeyJoinColumn

    private Brand brand;

    b) 在被控方:Brand

    @Id

    @GeneratedValue(generator=”myFG”)

    @GenericGenerator(name=”myFG”, strategy=”foreign”,parameters=@Parameter(name=”property”,value=”car”))

    private String id;

    @OneToOne(mappedBy=”brand”)

    private Car car;

  8. 双向多对多

    1. 在主控方:

    //从学生到课程的多对多: 最好由某一端来维护这个关系会更有效率

    @ManyToMany

    @JoinTable(name=”student_course”,

    joinColumns={@JoinColumn(name=”student_id”)},

    inverseJoinColumns={@JoinColumn(name=”course_id”)})

    private Set courseSet = new HashSet();

    1. 在被控方:

    //课程到学生的多对多

    @ManyToMany(mappedBy=”courseSet”)

    private Set stus = new HashSet();

  9. 把双向多对多拆成两个一对多: 1–>*<–1

  10. 继承映射:

    1. 整个继承树一张表

    在父类中添加从下注解

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(name=”type”,length=3)

@DiscriminatorValue(“u”)

子类中添加以下注解

@Entity

@DiscriminatorValue(“w”)

  1. 每个子类一张表

在父类添加如下注解

@Entity

@Table(name=”user”)

@Inheritance(strategy=InheritanceType.JOINED)

在子类中跟普通实体类的映射相同

  1. 每个具体类一张表

在父类中

@Entity

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

public class User {

@Id

@GeneratedValue(strategy=GenerationType.TABLE,generator=”xxGen”)

@TableGenerator(name=”xxGen”,allocationSize=1)

private Long id;

}

在子类中跟普通实体类的映射相同

  1. 组件映射

    在组件类中用@Emabbedable

    在使用这个组件类中用

    @Emabbed

    @AttributeOverrides({

    @AttributeOverride(name=”email”, column=@Column(name=”p_email”)),

    @AttributeOverride(name=”address”, column=@Column(name=”p_address”)),

    @AttributeOverride(name=”mobile”, column=@Column(name=”p_mobile”))

    })

  2. 联合主键映射

    1. 主键类:用@Emabbedable映射。并实现Serializable接口,使用主键属性重写hashCode()和equals()方法。

    2. 使用这个主键类的类中。用@Id映射。