public class Person {
private Integer pid;
private String name;
private Address address;
...
}
----------------------------------------
public class Address {
private Integer aid;
private String name;
private Person person;
...
}
1.0 基于外键的一对一
<?xml version="1.0" encoding="UTF-8"?>
<!-- Person.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
<class name="Person" table="t_Person" >
<id name="pid" column="pid">
<generator class="native"></generator>
</id>
<property name="name"></property>
<many-to-one name="address" class="Address" column="aid" unique="true"></many-to-one>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Address.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
<class name="Address" table="t_Address" >
<id name="aid" column="aid">
<generator class="native"></generator>
</id>
<property name="name"></property>
<!-- property-ref指定关联类的一个属性,来对应自己,意思是:person的address指向我 -->
<one-to-one name="person" property-ref="address" class="Person"/>
</class>
</hibernate-mapping>
mysql> show create table t_person;
+----------+--------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-----------------------------------+
| Table | Create Table
|
+----------+--------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-----------------------------------+
| t_person | CREATE TABLE `t_person` (
`pid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`aid` int(11) DEFAULT NULL,
PRIMARY KEY (`pid`),
UNIQUE KEY `aid` (`aid`),
KEY `FK41C0D9A019FE94E7` (`aid`),
CONSTRAINT `FK41C0D9A019FE94E7` FOREIGN KEY (`aid`) REFERENCES `t_address` (`a
id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+----------+--------------------------------------------------------------------
说白了,其实是一种特殊的一对多,多个person对一个address,但是person必须不重复
1.1添加
@Test
public void add(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Person p=new Person("好人刘强东");
Address a=new Address("中关村");
p.setAddress(a);
session.save(p);
session.save(a);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
1.2查找
@Test
public void find(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Person p=(Person) session.get(Person.class, 1);
// System.out.println(p.getAddress());
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
这里主要的问题是,他不级联查
Hibernate:
select
person0_.pid as pid1_0_,
person0_.name as name1_0_,
person0_.aid as aid1_0_
from
t_Person person0_
where
person0_.pid=?
通过另一端address来查,
@Test
public void findByAddress(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Address a=(Address) session.get(Address.class, 1);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
address0_.aid as aid0_1_,
address0_.name as name0_1_,
person1_.pid as pid1_0_,
person1_.name as name1_0_,
person1_.aid as aid1_0_
from
t_Address address0_
left outer join
t_Person person1_
on address0_.aid=person1_.aid
where
address0_.aid=?
结论: one-to-one 标签修饰后,他是主动选择每次查询都用join的,这里因为一对一不需要考虑数据集太大的问题;
@Test
public void update(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Address a=(Address) session.get(Address.class, 1);
a.getPerson().setName("刘强东");
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
address0_.aid as aid0_1_,
address0_.name as name0_1_,
person1_.pid as pid1_0_,
person1_.name as name1_0_,
person1_.aid as aid1_0_
from
t_Address address0_
left outer join
t_Person person1_
on address0_.aid=person1_.aid
where
address0_.aid=?
Hibernate:
update
t_Person
set
name=?,
aid=?
where
pid=?
1.3删除
@Test
public void deleteByAddress(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Address a=(Address) session.get(Address.class, 1);
session.delete(a);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
这里会出错,正确的方法:
@Test
public void deleteByPerson(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Person p=(Person)session.get(Person.class, 1);
session.delete(p);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
主要是因为:
2.0 同步主键式的一对一
<?xml version="1.0" encoding="UTF-8"?>
<!-- Address.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
<class name="Address" table="t_Address" >
<id name="aid" column="aid">
<generator class="foreign">
<!-- 主键根据哪个一属性对应的表来生成,这里是属性名,切记 -->
<param name="property">person</param>
</generator>
</id>
<property name="name"></property>
<!--
constrained: 约束
name:依然是属性名
-->
<one-to-one name="person" constrained="true"/>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Person.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
<class name="Person" table="t_Person" >
<id name="pid" column="pid">
<!-- 由这里提供主键 -->
<generator class="native"></generator>
</id>
<property name="name"></property>
<one-to-one name="address"/>
</class>
</hibernate-mapping>
2.1 添加
@Test
public void add(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Person p=new Person("好人刘强东");
Address a=new Address("中关村");
a.setPerson(p);
p.setAddress(a);
session.save(p);
session.save(a);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
结果:
Hibernate:
insert
into
t_Person
(name)
values
(?)
Hibernate:
insert
into
t_Address
(name, aid)
values
(?, ?)
2.2.1级联添加
<one-to-one name="address" cascade="all"/>
@Test
public void add(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Person p=new Person("好人刘强东");
Address a=new Address("中关村");
a.setPerson(p);
p.setAddress(a);
session.save(p);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
insert
into
t_Person
(name)
values
(?)
Hibernate:
insert
into
t_Address
(name, aid)
values
(?, ?)
2.2 更新
删掉级联,继续
考虑更新
@Test
public void updateByAddress(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Address a=(Address) session.get(Address.class, 1);
a.getPerson().setName("刘强东");
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
address0_.aid as aid0_0_,
address0_.name as name0_0_
from
t_Address address0_
where
address0_.aid=?
Hibernate:
select
person0_.pid as pid1_1_,
person0_.name as name1_1_,
address1_.aid as aid0_0_,
address1_.name as name0_0_
from
t_Person person0_
left outer join
t_Address address1_
on person0_.pid=address1_.aid
where
person0_.pid=?
Hibernate:
update
t_Person
set
name=?
where
pid=?
2.3 删除
@Test
public void deleteByAddress(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Address a=(Address) session.get(Address.class, 1);
session.delete(a);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
结果只删除了address,因为没有设级联
2.3.1 级联删除
添加级联
<!--person-->
<one-to-one name="address" cascade="all"/>
public void deleteByPerson(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// ------------------------------------------------------
Person p=(Person)session.get(Person.class, 1);
session.delete(p);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
person0_.pid as pid1_1_,
person0_.name as name1_1_,
address1_.aid as aid0_0_,
address1_.name as name0_0_
from
t_Person person0_
left outer join
t_Address address1_
on person0_.pid=address1_.aid
where
person0_.pid=?
Hibernate:
delete
from
t_Address
where
aid=?
Hibernate:
delete
from
t_Person
where
pid=?