八 一对一 用户与身份证的关系
设计用户实体 主实体
package hibernate.bean;
public class Person {
private int id;
private String name;
private IDCard idcart;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public IDCard getIdcart() {
return idcart;
}
public void setIdcart(IDCard idcart) {
this.idcart = idcart;
}
}
映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="hibernate.bean">
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<one-to-one name="idcart"/>
</class>
</hibernate-mapping>
设计身份证实体 从实体
package hibernate.bean;
public class IDCard {
private int id;
private String useDate;
private Person person;
public String getUseDate() {
return useDate;
}
public void setUseDate(String useDate) {
this.useDate = useDate;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernate.bean">
<class name="IDCard" table="id_card">
<id name="id">
<!-- 设置主键为外键 关联的是主实体的id-->
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property column="use_date" name="useDate"/>
<one-to-one name="person"/>
</class>
</hibernate-mapping>
测试
package hibernate.test;
import hibernate.bean.IDCard;
import hibernate.bean.Person;
import hibernate.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class OneToOne {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
add();
query(1);
}
static Person add(){
Session session=null;
Transaction tx=null;
try{
session=HibernateUtil.getSession();
tx=session.beginTransaction();
IDCard idcard=new IDCard();
idcard.setUseDate("有效期三年");
Person person=new Person();
person.setName("许春荣");
// person.setIdcart(idcard);
idcard.setPerson(person);
session.save(person);
session.save(idcard);
tx.commit();
return person;
}finally{
if(session!=null) session.close();
}
}
static void query(int id){
Session session=null;
try{
session=HibernateUtil.getSession();
Person person=(Person)session.get(Person.class, id);
System.out.println(person.getName()+"-------->"+person.getIdcart().getUseDate());
}finally{
if(session!=null) session.close();
}
}
}
分析:在执行后,我们可以去查看一下从实体下的表结构 在命令行输入 show create table id_card
源码为 ddl语句
CREATE TABLE `id_card` (
`id` int(11) NOT NULL,
`use_date` varchar(255) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
发现生成的表的主键少了一个定义,根据我们的设计 id_card表的id 不但要是主键也要是外键,它引用的是
person表的主键 为什么是这样呢?其实这样并不会影响我们程序的实体的实现效果,为了设计更合理,我们必须要注意
在Person的映射文件的one-to-one节点中 少了一个属性constrained定义,加上<one-to-one name=”idCard” constrained=”true”/>
ddl语句
CREATE TABLE `id_card` (
`id` int(11) NOT NULL,
`use_date` varchar(255) default NULL,
PRIMARY KEY (`id`),
KEY `FK627C1FB461BB04F2` (`id`),
CONSTRAINT `FK627C1FB461BB04F2` FOREIGN KEY (`id`) REFERENCES `person` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
这样是不是更合理呢
下面我们来看第二种一对一的设计方式
上面的这种设计方式是把从表的主键id是依赖于主表的主键id而建立的
我们可不可以改变这样的设计方式,而在从表中额外加入一个外键呢
但是,如果我们这样做的话,我们可以在从表下根据一个主表的id,而在从表中加入多条数据
这样不就是多对一的关系了吗?是这样的,但是我们是否可以把这个外键同时也设置为唯一键呢
哈哈,这不就好了,这只是要修改映射文件即可实现,怎么修改的 请看吧
Person实体的映射文件
修改前
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="hibernate.bean">
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<one-to-one name="idcart"/>
</class>
</hibernate-mapping>
修改后
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="hibernate.bean">
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!-- 这里的property-ref="person" 是IDCard的属性 用这来告诉hibernate的从实体隶属于Person
-->
<one-to-one name="idcart" property-ref="person"/>
</class>
</hibernate-mapping>
IDCard的映射文件
修改前
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernate.bean">
<class name="IDCard" table="id_card">
<id name="id">
<!-- 设置主键为外键 关联的是主实体的id-->
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property column="use_date" name="useDate"/>
<one-to-one name="person" constrained=”true”/>
</class>
</hibernate-mapping>
修改后的
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernate.bean">
<class name="IDCard" table="id_card">
<id name="id">
<!-- 设置主键为外键 关联的是主实体的id-->
<!--
<generator class="foreign">
<param name="property">person</param>
</generator>
-->
<generator class="native"/>
</id>
<property column="use_date" name="useDate"/>
<!-- 在这里加入了many-to-one 而不是one-to-one 并且指定其隶属的实体 Person unique是指定其唯一键
column制定其唯一键的列名 -->
<many-to-one name="person" unique="true" column="person_id"/>
</class>
</hibernate-mapping>
然后就可以运行测试文件 成功执行
现在我们来查看id_card表的ddl语句 show create table id_card;
CREATE TABLE `id_card` (
`id` int(11) NOT NULL auto_increment,
`use_date` varchar(255) default NULL,
`person_id` int(11) default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `person_id` (`person_id`),
KEY `FK627C1FB49495921C` (`person_id`),
CONSTRAINT `FK627C1FB49495921C` FOREIGN KEY (`person_id`) REFERENCES `person` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
发现person_id是个外键 并且还是个唯一键
到这里一对一的映射就完成了
完毕 end!