1) 数据库表的设计
1> 基于外键方式
即在其中一方增加一个外键,指向另一张表的主键,并添加unique约束(否则不加就是一对多了)
2> 基于主键方式
即另一张表的主键就是外键,指向另一张表的主键
3> 比较
基于外键方式的记录可以单独存在,基于主键的方式由于引用的是其他表的主键,所以如果其他表中相关记录不存在,本表中记录也不会存在。
2) 基于外键的方式
1> pojo设计
public class IdCard {
private int id;
private String num;
private Person person;
}
public class Person {
private int id;
private String name;
private IdCard idCard;
}
2> 映射文件
<class name="cn.com.cpf.pojo.IdCard" table="t_idCard" >
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="num"/>
<many-to-one name="person" class="cn.com.cpf.pojo.Person" unique="true" column="personId" />
</class>
因为在一对一中和多对一只不过就是在外键多了一个唯一性约束,所以标签用的还是多对一的
<class name="cn.com.cpf.pojo.Person" table="t_person" >
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<one-to-one name="idCard" class="cn.com.cpf.pojo.IdCard" property-ref="person" ></one-to-one>
</class>
在本方使用property-ref属性来指定关联的外键对应的pojo属性
3> 生成的数据库表结构
维护关系的表:
另一张表:
4>保存
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Person person = new Person();
person.setName("xny");
IdCard idCard = new IdCard();
idCard.setNum("22X");
idCard.setPerson(person);
person.setIdCard(idCard);
session.save(person);
session.save(idCard);
结果:
Hibernate: insert into t_person (name) values (?)
Hibernate: insert into t_idCard (num, personId) values (?, ?)
5> 查询
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Person person = (Person) session.get(Person.class, 1);
System.out.println(person.getName()+" "+person.getIdCard());
IdCard idCard = (IdCard) session.get(IdCard.class, 1);
System.out.println(idCard.getNum()+" "+idCard.getPerson());
结果为:
Hibernate: select person0_.id as id1_6_0_, person0_.name as name2_6_0_, idcard1_.id as id1_5_1_, idcard1_.num as num2_5_1_, idcard1_.personId as personId3_5_1_ from t_person person0_ left outer join t_idCard idcard1_ on person0_.id=idcard1_.personId where person0_.id=?
zq cn.com.cpf.pojo.IdCard@2e9dca26
11X cn.com.cpf.pojo.Person@32b3a5a0
6> 解除关系
从有外键的一方解除:
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
IdCard idCard = (IdCard) session.get(IdCard.class, 1);
idCard.setPerson(null);
tx.commit();
结果为:
Hibernate: select idcard0_.id as id1_5_0_, idcard0_.num as num2_5_0_, idcard0_.personId as personId3_5_0_ from t_idCard idcard0_ where idcard0_.id=?
Hibernate: update t_idCard set num=?, personId=? where id=?
从无外键的一方解除
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Person person = (Person) session.get(Person.class, 2);
person.setIdCard(null);
tx.commit();
结果为:
Hibernate: select person0_.id as id1_6_0_, person0_.name as name2_6_0_, idcard1_.id as id1_5_1_, idcard1_.num as num2_5_1_, idcard1_.personId as personId3_5_1_ from t_person person0_ left outer join t_idCard idcard1_ on person0_.id=idcard1_.personId where person0_.id=?
无update语句,说明并没有解除关系
7> 删除
从无外键的一方删除
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Person person = (Person) session.get(Person.class, 2);
session.delete(person);
tx.commit();
结果为:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t_idcard`, CONSTRAINT `FK_k76g8cd5pddkq5qesjleu60ts` FOREIGN KEY (`personId`) REFERENCES `t_person` (`id`))
从有外键的一方删除
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
IdCard idCard = (IdCard) session.get(IdCard.class, 2);
session.delete(idCard);
tx.commit();
结果为:
Hibernate: select idcard0_.id as id1_5_0_, idcard0_.num as num2_5_0_, idcard0_.personId as personId3_5_0_ from t_idCard idcard0_ where idcard0_.id=?
Hibernate: delete from t_idCard where id=?
成功删除
7> 因为在一对一关系中只有一方维护关系,所以只能从维护外键的一方执行解除关系和删除操作
3) 基于主键的方式
1> pojo
和基于外键的完全相同
2> 映射文件
无外键一方:
<class name="cn.com.cpf.pojo.Person" table="t_person2" >
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<one-to-one name="idCard" class="cn.com.cpf.pojo.IdCard"/>
</class>
有外键一方:
<class name="cn.com.cpf.pojo.IdCard" table="t_idCard2" >
<id name="id" column="id">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="num"/>
<one-to-one name="person" class="cn.com.cpf.pojo.Person" constrained="true"/>
</class>
1.主键的生成方式为foreign,其中需要配property参数,值为依赖的其id的那个对象
2.在one-to-one标签中,需要设置constrained为true
3> 生成的数据库表
维护外键的表:
不维护外键的表:
4> 解除关联关系
由于是基于主键的关联,且因为不能设置主键为null,所以不论是哪一方都无法解除关系