hibernate annotation 双向 onetoone 注解.docx
《hibernate annotation 双向 onetoone 注解.docx》由会员分享,可在线阅读,更多相关《hibernate annotation 双向 onetoone 注解.docx(31页珍藏版)》请在冰豆网上搜索。
![hibernate annotation 双向 onetoone 注解.docx](https://file1.bdocx.com/fileroot1/2023-1/26/fd1f2b9c-8db1-4dd6-be22-bc6ef6b18181/fd1f2b9c-8db1-4dd6-be22-bc6ef6b181811.gif)
hibernateannotation双向onetoone注解
hibernateannotation双向one-to-one注解
环境:
Hibernate3.3.1
Maven3.0.4
MySQL5.5.13
Myeclipse8.6.1
建表语句:
DROPTABLEIFEXISTS`t_card`;
CREATETABLE`t_card`(
`cardId`int(10)unsignedNOTNULLAUTO_INCREMENT,
`cardNumber`char(18)NOTNULL,
PRIMARYKEY(`cardId`)
)ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=gb2312;
INSERTINTO`t_card`VALUES('1','440911199008011122');
DROPTABLEIFEXISTS`t_person`;
CREATETABLE`t_person`(
`personId`int(10)unsignedNOTNULLAUTO_INCREMENT,
`personName`varchar(15)NOTNULL,
`cid`int(10)unsignedNOTNULL,
PRIMARYKEY(`personId`)
)ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=gb2312;
INSERTINTO`t_person`VALUES('1','fancy','1');
Person.java
packagecom.fancy.po;
importjavax.persistence.CascadeType;
importjavax.persistence.Entity;
importjavax.persistence.GeneratedValue;
importjavax.persistence.GenerationType;
importjavax.persistence.Id;
importjavax.persistence.JoinColumn;
importjavax.persistence.OneToOne;
importjavax.persistence.Table;
/**
*-----------------------------------------
*@文件:
Person.java
*@作者:
fancy
*@邮箱:
fancyzero@
*@时间:
2012-6-10
*@描述:
实体类
*-----------------------------------------
*/
/**
*@Entity声明一个类为实体Bean
*@Table(name="xx")指定实体类映射的表,如果表名和实体类名一致,可以不指定
*/
@Entity
@Table(name="t_person")
publicclassPerson{
privateIntegerpersonId;
privateStringpersonName;
privateCardcard;
/**
*@Id映射主键属性,这里采用uuid的主键生成策略
*@GeneratedValue——注解声明了主键的生成策略。
该注解有如下属性
*strategy指定生成的策略,默认是GenerationType.AUTO
*GenerationType.AUTO主键由程序控制
*GenerationType.TABLE使用一个特定的数据库表格来保存主键
*GenerationType.IDENTITY主键由数据库自动生成,主要是自动增长类型
*GenerationType.SEQUENCE根据底层数据库的序列来生成主键,条件是数据库支持序列
*generator指定生成主键使用的生成器
*/
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
publicIntegergetPersonId(){
returnpersonId;
}
/**
*@OneToOne:
一对一关联
*cascade:
级联,它可以有有五个值可选,分别是:
*CascadeType.PERSIST:
级联新建
*CascadeType.REMOVE:
级联删除
*CascadeType.REFRESH:
级联刷新
*CascadeType.MERGE:
级联更新
*CascadeType.ALL:
以上全部四项
*@JoinColumn:
主表外键字段
*cid:
Person所映射的表中的一个字段
*/
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="cid")
publicCardgetCard(){
returncard;
}
publicStringgetPersonName(){
returnpersonName;
}
publicvoidsetPersonId(IntegerpersonId){
this.personId=personId;
}
publicvoidsetPersonName(StringpersonName){
this.personName=personName;
}
publicvoidsetCard(Cardcard){
this.card=card;
}
}
Card.java
packagecom.fancy.po;
importjavax.persistence.Entity;
importjavax.persistence.GeneratedValue;
importjavax.persistence.GenerationType;
importjavax.persistence.Id;
importjavax.persistence.OneToOne;
importjavax.persistence.Table;
/**
*-----------------------------------------
*@文件:
Card.java
*@作者:
fancy
*@邮箱:
fancyzero@
*@时间:
2012-6-10
*@描述:
实体类
*-----------------------------------------
*/
@Entity
@Table(name="t_card")
publicclassCard{
privateIntegercardId;
privateStringcardNumber;
privatePersonperson;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
publicIntegergetCardId(){
returncardId;
}
/**
*@OneToOne:
一对一关联
*mappedBy="card":
意思是说这里的一对一配置参考了card
*card又是什么呢?
card是Person类中的getCard(),注意不是Person类中的
*card属性,Person类中的OneToOne配置就是在getCard()方法上面配的.
*如果Person类中的getCard()方法改成getIdCard(),其他不变的话,
*这里就要写成:
mappedBy="idCard"
*/
@OneToOne(mappedBy="card")
publicPersongetPerson(){
returnperson;
}
publicStringgetCardNumber(){
returncardNumber;
}
publicvoidsetCardId(IntegercardId){
this.cardId=cardId;
}
publicvoidsetCardNumber(StringcardNumber){
this.cardNumber=cardNumber;
}
publicvoidsetPerson(Personperson){
this.person=person;
}
}
pom.xml
//maven.apache.org/POM/4.0.0"xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance"
xsi:
schemaLocation="http:
//maven.apache.org/POM/4.0.0http:
//maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.fancy
hibernate-annotation-on-to-one-example
0.0.1-SNAPSHOT
jar
hibernate-annotation-on-to-one-example
http:
//maven.apache.org
UTF-8
--hibernatejar-->
org.hibernate
hibernate-entitymanager
3.3.1.ga
--hibernateannotationjar-->
org.hibernate
hibernate-annotations
3.3.1.GA
--mysql-->
mysql
mysql-connector-java
5.1.17
junit
junit
3.8.1
test
在生成数据库表的过程中,
报 javax.persistence.OneToMany.orphanRemoval()Z异常的解决方法:
去掉myeclipse中的j2ee包居然就可以了!
!
@oneToMany(mappedBy="另一方类中对应的属性名(外键)",cascade=CascadeType.ALL,fetch=FetchType.EAGER)就相当于xml配置中的inverse=true
在单向关系中没有mappedBy。
mappedBy一定是定义在theownedside(被拥有方的),他指向theowningside(拥有方);
主控方相当于拥有指向另一方的外键的一方。
mappedBy指定的是不需要维护关系的一端
@ManyToOne
@JoinColumn(name="外键的字段名")
1.一对一和多对一的@JoinColumn注解的都是在“主控方”,都是本表指向外表的外键名称。
2.一对多的@JoinColumn注解在“被控方”,即一的一方,指的是外表中指向本表的外键名称。
3.多对多中,joinColumns写的都是本表在中间表的外键名称,
inverseJoinColumns写的是另一个表在中间表的外键名称。
mappedBy跟JoinColumn/JoinTable总是处于互斥的一方
如产品类型和产品的关系:
@Entity
@Table(name="tb_productType")//经常给漏掉这东西
publicclassProductTypeextendsBaseBean
{
privatestaticfinallongserialVersionUID=3466104768256418884L;
@Column(nullable=false,unique=true)
privateStringname;
@OneToMany(mappedBy="type",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
privateListproducts;
...
和:
@Entity
@Table(name="tb_product")
publicclassProductextendsBaseBean
{
privatestaticfinallongserialVersionUID=4109238647414563541L;
@Column(nullable=false)
privateStringname;
@Column(precision=2)
privatedoubleprice;
@Basic(fetch=FetchType.LAZY)
@Column(columnDefinition="longtext")
privateStringintro;
privateStringmasterDrowing;
@ManyToOne
@JoinColumn(name="productType_id")
privateProductTypetype;
privateStringcomment;
privateinthit;
privatebooleanfinalRealse;
privateintcount;
@ManyToOne
@JoinColumn(name="person_id")
privatePersoncontacter;
@Temporal(value=TemporalType.DATE)
privateDaterealseDate;
...
hibernate的配置文件:
com.mysql.jdbc.Driver
jdbc:
mysql:
//localhost:
3306/site?
characterEncoding=UTF-8
root
root
org.hibernate.dialect.MySQLDialect
true
create
--要加这一句 否则可能会遇到异常-->
thread
产生数据库表的类:
createTable类
importorg.hibernate.cfg.AnnotationConfiguration;
importorg.hibernate.tool.hbm2ddl.SchemaExport;
publicclassCreateTable{
staticvoidcreate(){
SchemaExportexport=newSchemaExport(newAnnotationConfiguration().configure());
export.create(true,true);
}
publicstaticvoidmain(String[]args){
create();
}
}
经过这些配置就可以生成数据库表了!
!
单向关系中的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")//注释的是另一个表指向本表的外键。
publicListgetPhones(){
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);
所以我们最好还是指定一下,以让程序产生更加确定的行为,不过一般是推荐另外生成一个中间表好一些,因为这样的话,对原来两张表的结构不对造成任何影响。
在遗留系统的时候很多用,有些时候,一些表都是以前就建好了的,要改表的结构是不太可能的,所以这个时候中间的表就显得很重要了,它可以在不侵入原来表的情况下构建出一种更清淅更易管理的关系。
所以一对多的单向关联,我们还是推荐使用一张中间表来建立关系。