hibernate入门二:一对一关联关系映射

  在hibernate中一对一关联关系映射有两种方式:共享主键和唯一外键。共享主键就是两张表的主键值都用一个值,唯一外键,顾名思义,即是在外键上加上唯一性约束。但无论是哪种方式,如果表中存在主从关系,在使用DAO的save方法保存从对象时,都必须先将主对象属性通过set方法先添加。
比如有2个类:
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脚本和映射文件及对应的类,其实SQL中的外键关系在数据库表中都不用体现,因为有Hibernate映射文件约束,但为了清楚和手动插入数据的完整性,还是加上了。
    数据库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>

猜你喜欢

转载自dr-yanglong.iteye.com/blog/1937060