您的位置:首页 > 其它

@JoinColumn

2015-04-10 14:44 169 查看
@OneToOne注释只能确定实体与实体的关系是一对一的关系,不能指定数据库表中的保存的关联字段。所以此时要结合@JoinColumn标记来指定保存实体关系的配置。

@JoinColumn与本书上一章讲述的@Column注释类似,它的定义如下代码所示。

@Target({METHOD,FIELD})@Retention(RUNTIME)

public@interfaceJoinColumn{

Stringname()default"";

StringreferencedColumnName()default"";

booleanunique()defaultfalse;

booleannullable()defaulttrue;

booleaninsertable()defaulttrue;

booleanupdatable()defaulttrue;

StringcolumnDefinition()default"";

Stringtable()default"";

}

在使用@JoinColumn注释时,应注意以下几个问题。

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

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

@JoinColumn与@Column标记一样,name属性是用来标识表中所对应的字段的名称。例如customer表中存在字段addr_id,标识的代码如下所示。

@OneToOne

@JoinColumn(name="addr_id")

publicAddressEOgetAddress(){

returnaddress;

}

若此时,不设置name的值,则在默认情况下,name的取值遵循以下规则:

name=关联表的名称+“_”+关联表主键的字段名

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

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

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

CREATETABLEaddress(

idint(20)NOTNULLauto_increment,

ref_idintint(20)NOTNULL,

provincevarchar(50),

cityvarchar(50),

postcodevarchar(50),

detailvarchar(50),

PRIMARYKEY(id)

)

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

@OneToOne

@JoinColumn(name="address_id",referencedColumnName="ref_id")

publicAddressEOgetAddress(){

returnaddress;

}

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

JoinColumn标记不仅能够与@OneToOne使用,也可以@ManyToOne或@ManyToMany标记同时使用,它们所表示的含义不同。

单向关系中的@JoinColumn

1.person与address的一对一单向关系:

在address中没有特殊的注解。

在Person中对应到数据库里面就有一个指向Address的外键.

我们也可以增加注释指定外键的列的名字,如下:

@OneToOne(cascade=CascadeType.ALL,optional=true)

@JoinColumn(name="addressID")//注释本表中指向另一个表的外键。

publicAddressgetAddress(){

returnaddress;

}

如果我们不加的话,也是可以通过的,在JBOSS里面,它会自动帮你生成你指向这个类的类名加上下划线再加上id的列,也就是默认列名是:address_id.

如果是主键相关联的话,那么可以运用如下注释

@OneToOne(cascade={CascadeType.ALL})

@PrimaryKeyJoinColumn

publicAddressgetAddress(){

returnhomeAddress;

}

它表示两张表的关联是根据两张表的主键的

—————————————————————————————————————————————————————————————————————

2.person和phone的一对多单向关系:

phone中没有特别的注释。

person中:

@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="personID")//注释的是另一个表指向本表的外键。
publicList<Phone>getPhones(){
returnphones;
}


我们可以在Person类里面发现@JoinColumn(name="personID")

它代表是一对多,一是指类本身,多是指这个成员,也就是一个类可以对应多个成员.

在一对多里面,无论是单向还是双向,映射关
系的维护端都是在多的那一方,也就是Phone那里,因为要在数据库面表现的话,也只有让Phone起一个指向Person的外键,不可能在Person
里面指向Phone,这一点和一对一不一样,一对一可以在任意一方起一个外键指向对方.可是一对多却不行了
.

在这里@JoinColumn这个注释指的却是在Phone里面的外键的列的名字,

它并不像在一对一里面的注释指的是自己表里面的外键列名.这一点要特别注意一下.

如果是一对多的双向关系,那么这个注释就要应用到多的那边去了,虽然注释还在Person类里面,但是它起的效果却是在Phone里面起一个叫personID的外键,因为多的那边要有外键指向少的这边.

如果你不加@JoinColumn(name="personID")这个注释的话,那么JBOSS就会自动帮你生成一张中间表,

它负现Person和Phone表之间的联系.它将会做如下事情:

CREATETABLEPERSON_PHONE
(
PERSON_idINT,
PHONE_idINT
);
ALTERTABLEPERSON_PHONEADDCONSTRAINTperson_phone_unique
UNIQUE(PHONE_id);

ALTERTABLEPERSON_PHONEADDCONSTRAINTpersonREFphone
FOREIGNKEY(PERSON_id)REFERENCESPERSON(id);

ALTERTABLEPERSON_PHONEADDCONSTRAINTpersonREFphone2
FOREIGNKEY(PHONE_id)REFERENCESPHONE(id);

所以我们最好还是指定一下,以让程序产生更加确定的行为,不过一般是推荐另外生成一个中间表好一些,因为这样的话,对原来两张表的结构不对造成任何影响。在遗留系统的时候很多用,有些时候,一些表都是以前就建好了的,要改表的结构是不太可能的,所以这个时候中间的表就显得很重要了,它可以在不侵入原来表的情况下构建出一种更清淅更易管理的关系。

所以一对多的单向关联,我们还是推荐使用一张中间表来建立关系。

---------------------------------------------------------------------------------------------------------------------------------------------

3.person和country的多对一单向关系:

country中无特别的注解。

而person注解如下:

@ManyToOne
@JoinColumn(name="countryID")
publicCountrygetCountry(){
returncountry;
}
在一对多一对多一对的关系里面,关系的维护端都是在多的那一面,多的一面为主控方,拥有指向对方的外键。

因为主控端是Person.外键也是建在Person上面,因为它是多的一面。当然我们在这里也可以省掉@JoinColumn,那样的话会怎么样呢,会不会像一对多单向一样生成中间的表呢?事实是不会的,在这里如果我们去掉@JoinColumn的话,那么一样会在Person表里面生成一列指向

Country的外键,这一点和一对多的单向是不一样,在一对多的单向里面,如果我们不在Person里面加上@JoinColumn这个注释,那么JBOSS将会为我们生成一个中间的表,这个表会有一个列指向Person主键,一个列指向Phone主键。所以说为了程序有一定的行为,有些东西我们还是不要省的好。

其实多对一单向是有点向一对一单向的,在主控端里面,也就是从Person的角度来看,也就是对应了一个Country而已,只不过这个Country是很多Person所共用的,而一对一却没有这一点限制。

------------------------------------------------------------------

4.person和project的多对多单向关系:

project没有特殊的注解。

person:

@ManyToMany

publicList<Project>getProjects(){
returnprojects;
}

它需要设置中间表来维护关系,在数据库上跟多对多双向,只不过在编程的逻辑中不一样而已。

//类似这个:@JoinTable(name="PersonANDFlight",joinColumns={@JoinColumn(name="personID")},

//inverseJoinColumns={@JoinColumn(name="flightID")})

其实这个声明不是必要的,当我们不用@JoinTable来声明的时候,JBOSS也会为我们自动生成一个连接用的表,

表名默认是主控端的表名加上下划线"_"再加上反转端的表名.

类似

@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="PersonANDFlight",

        joinColumns={@JoinColumn(name="personID")},

        inverseJoinColumns={@JoinColumn(name="flightID")})
publicList<Flight>getFlights(){
returnflights;
}


-------------------------------------------------------------------------

在单向关系中没有mappedBy,主控方相当于拥有指向另一方的外键的一方。

1.一对一和多对一的@JoinColumn注解的都是在“主控方”,都是本表指向外表的外键名称。

2.一对多的@JoinColumn注解在“被控方”,即一的一方,指的是外表中指向本表的外键名称。

3.多对多中,joinColumns写的都是本表在中间表的外键名称,

inverseJoinColumns写的是另一个表在中间表的外键名称

出自:http://blog.csdn.net/yingevil/article/details/6875418
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: