在
hibernate中一对一关联关系映射有两种方式:共享
主键和唯一
外键。共享主键就是两张表的主键值都用一个值,唯一外键,顾名思义,即是在外键上加上唯一性约束。但无论是哪种方式,如果表中存在主从关系,在使用DAO的save方法保存从对象时,都必须先将主对象属性通过set方法先添加。
比如有2个类:
class="java" name="code">
public class A{
private int id;
private B b;
//省略构造及getter,setter方法
}
public class B{
private int id;
//省略构造及getter,setter方法
}
B主A从,那么,在调用save方法保存A前,必须先用A的set方法将b属性对应的对象添加,否则失败。主对象可以单独保存。判断主从的依据是,既是主键又是外键,则为从。被参考的主键所在的表对应的则为主。
因为是整理,所以在说映射之前将一对一关系中的有的东西先说清楚。DAO代码不再附上,仅附上sql
脚本和映射文件及对应的类。
数据库MySQL5.6,脚本:
CREATE TABLE `address1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`city` varchar(40) DEFAULT NULL,
`street` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `adress` (
`id` int(11) NOT NULL DEFAULT '0',
`city` varchar(40) DEFAULT NULL,
`street` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_a_p` FOREIGN KEY (`id`) REFERENCES `person` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(16) DEFAULT NULL,
`gender` varchar(2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `person1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(16) DEFAULT NULL,
`gender` varchar(2) DEFAULT NULL,
`adress` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_p_ad` (`adress`),
CONSTRAINT `fk_p_ad` FOREIGN KEY (`adress`) REFERENCES `address1` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
一对一关系映射,共享主键方式:
类person为主,adress为从
package model;
/**
* Person entity
*/
public class Person implements java.io.Serializable {
private Integer id;
private Adress adress;
private String name;
private String gender;
/** default constructor */
public Person() {
}
/** full constructor */
public Person(Adress adress, String name, String gender) {
this.adress = adress;
this.name = name;
this.gender = gender;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public Adress getAdress() {
return this.adress;
}
public void setAdress(Adress adress) {
this.adress = adress;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return this.gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
package model;
/**
* Adress entity
*/
public class Adress implements java.io.Serializable {
private Integer id;
private String city;
private String street;
private Person person;
/** default constructor */
public Adress() {
}
/** full constructor */
public Adress(Integer id, String city, String street, Person person) {
this.id = id;
this.city = city;
this.street = street;
this.person = person;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return this.street;
}
public void setStreet(String street) {
this.street = street;
}
public Person getPerson() {
return this.person;
}
public void setPerson(Person person) {
this.person = person;
}
}
映射文件
Person.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.Person" table="person" catalog="study">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<!-- 一对一映射设置,检索策略立即加载 -->
<one-to-one name="adress" class="model.Adress" cascade="all" lazy="false"/>
<property name="name" type="java.lang.String">
<column name="name" length="16" />
</property>
<property name="gender" type="java.lang.String">
<column name="gender" length="2" />
</property>
</class>
</hibernate-mapping>
Adress.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.Adress" table="adress" catalog="study">
<id name="id" type="java.lang.Integer">
<column name="id" />
<!-- 使用外键生成器,直接采用外键的属性值作为主键值 -->
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="city" type="java.lang.String">
<column name="city" length="40" />
</property>
<property name="street" type="java.lang.String">
<column name="street" length="100" />
</property>
<!-- 一对一映射, constrained="true"说明主键上存在外键约束 -->
<one-to-one name="person" class="model.Person" constrained="true" />
</class>
</hibernate-mapping>
一对一关系映射,唯一外键方式:
类一样,映射文件不同,但为了清楚,还是稍作区别,其实只是类名改变了下。
类:
package model;
/**
* Person1 entity
*/
public class Person1 implements java.io.Serializable {
private Integer id;
private Address1 address1;
private String name;
private String gender;
/** default constructor */
public Person1() {
}
/** full constructor */
public Person1(Address1 address1, String name, String gender) {
this.address1 = address1;
this.name = name;
this.gender = gender;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public Address1 getAddress1() {
return this.address1;
}
public void setAddress1(Address1 address1) {
this.address1 = address1;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return this.gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
package model;
/**
* Address1 entity
*/
public class Address1 implements java.io.Serializable {
private Integer id;
private String city;
private String street;
private Person1 person1;
/** default constructor */
public Address1() {
}
/** full constructor */
public Address1(String city, String street, Person1 person1) {
this.city = city;
this.street = street;
this.person1 = person1;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return this.street;
}
public void setStreet(String street) {
this.street = street;
}
public Person1 getPerson1() {
return this.person1;
}
public void setPerson1s(Person1 person1) {
this.person1 = person1;
}
}
映射文件:
Person1.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.Person1" table="person1" catalog="study">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<!-- 一般来说采用外键会表现为一对多,参考方为多,被参考方为1,亦即是拥有外键约束的一方为多。但通过在外键上增加唯一性约束,将使得一对多变为一对一 -->
<many-to-one name="address1" class="model.Address1" lazy="false" cascade="true" unique="true">
<column name="adress" />
</many-to-one>
<property name="name" type="java.lang.String">
<column name="name" length="16" />
</property>
<property name="gender" type="java.lang.String">
<column name="gender" length="2" />
</property>
</class>
</hibernate-mapping>
Address1.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.Address1" table="address1" catalog="study">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<property name="city" type="java.lang.String">
<column name="city" length="40" />
</property>
<property name="street" type="java.lang.String">
<column name="street" length="100" />
</property>
<!-- 注意 property-ref属性,是指在person1类中定义address1类作为属性时的属性名称 -->
<one-to-one name="person1" class="model.Person1" property-ref="address1" />
</class>
</hibernate-mapping>