前几篇我讲解了一下Hibernate框架的搭建与使用~
这次我就说一下数据库里面的关联映射的一对一~
这个一对一关联可以有俩种方式来映射:通过外键来映射和通过主键来映射
一对一关联可以通过举个例子来说明-----一个人对应一张身份证
一,通过外键来映射
1.先把POJO类写出来
Person类:
public class Person {
//基本属性
private Long id;
private String name;
//关联属性
private Card card;
public Person(Long id, String name) {
super();
this.id = id;
this.name = name;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
}
Card类:
//身份证
public class Card {
private Long id;
private String number;//身份证号
private String address;//地址
private Person person;
public Card(Long id, String number, String address) {
super();
this.id = id;
this.number = number;
this.address = address;
}
public Card() {
super();
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
2.POJO类写好了,那就开始写映射文件吧,把它们的关系表达出来
在这里我设定Person是主方~
分析一下它们的关系啊~
是1:n一种特例
Person(主)
id name age
101 terry 12
card(从)
id num date p_id
1 1001 101
2 1002 101
所以映射文件开始写了~
person.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.xu.day5.one2one">
<!-- 通过外键维护 -->
<class name="Person" table="tb_person">
<id name="id" column="id">
<generator class="increment"/>
</id>
<property name="name" />
<!-- 在主方一对一 -->
<!-- 一对一 property-ref指定关联类的属性名,
这个属性将会和本类(Person)的主键相对应(Card的外键)。
如果没有指定,
会使用对方关联类(Card)的主键。 -->
<one-to-one name="card" class="Card" property-ref="person"/>
<!-- property-ref="person"
没有指定默认的是主方的主键找从方的主键
指定了的话是主方的主键找从方的外键-->
</class>
</hibernate-mapping>
card.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.xu.day5.one2one">
<!--通过外键维护 -->
<class name="Card" table="tb_card">
<id name="id" column="id">
<generator class="increment" />
</id>
<property name="number" />
<property name="address" />
<!-- 多对一,多-要么是1个,或者0个,p_id是Card的外键 -->
<many-to-one name="person" class="Person"
unique="true" column="p_id"
/>
</class>
</hibernate-mapping>
映射外键到这里就配置完成了~
接下来就要把映射文件集成到配置文件上~
3.编写配置文件hibernate.cfg.xml~
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://127.0.0.1:3306/ssh</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="com/xu/day5/one2one/person.hbm.xml" />
<mapping resource="com/xu/day5/one2one/card.hbm.xml" />
</session-factory>
</hibernate-configuration>
4.编写测试类MainTest:
public class MainTest {
public static void main(String[] args) {
Session session=HibernateSessioFactory.getSession();
Transaction tr=session.beginTransaction();
System.out.println("onetoone");
//1.//张三出生
Person p=new Person(null, "张三");
session.save(p);
tr.commit();
}
}
这里模拟了张三的出生,这时候他还没有身份证~
运行效果如下:
我还想模拟张三办身份证~
把上面的关键代码改成如下:
//张三办身份证
Person p=(Person) session.load(Person.class, 1L);
Card c=new Card(null, "12446261787123", "江西");
c.setPerson(p);//维护外键-person与Card p_id
session.save(c);
我在运行一遍啊~
注意:
unique="true" 是在使用hibernate的自动建表的时候才用到,用来指定表中的外键唯一,即给表中的外键添加唯一性约束,保证是一对一的关系
property-ref="" 用来指定关联类的属性名,这个属性将会和本类中的主键相对应,如果没有指定,默认使用关联类的主键和本类中的主键相对应。
在一对一关系中,如果没有在<one-to-one>中指定property-ref="person",当从主方对象寻找从方对象的时候将会使用自身的主键和关联类的主键匹配,这样就会出问题!如果指定后,将会用自身的主键和关联类的外键匹配。property-ref=""中的值为属性。
好了,通过外键维护就完成了~
现在来写主键维护~
二,通过主键来维护
分析:
从表的ID和主表的ID保持一致
Person(主)
id name age
101 terry 12
102 larry 12
card(从)
id numdate
101 1001
102 1002
这时候只需要改映射文件~
person.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.xu.day5.one2one">
<!-- 通过主键维护 -->
<class name="Person" table="tb_person">
<id name="id" column="id">
<generator class="increment" />
</id>
<property name="name" />
<!-- 在主方一对一 -->
<one-to-one name="card" class="Card"/>
</class>
</hibernate-mapping>
card.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.xu.day5.one2one">
<!-- 通过主键维护 -->
<class name="Card" table="tb_card">
<id name="id" column="id">
<!-- 这个Card的id是和Person的id是一样的,参照的是Card类中的关联属性person -->
<generator class="foreign" >
<param name="property">person</param>
</generator>
</id>
<property name="number" />
<property name="address" />
<!-- 从方 多对一,多-要么是1个,或者0个 -->
<many-to-one name="person" class="Person"
/>
</class>
</hibernate-mapping>
运行效果都是一样的,我这里就不运行了~
注意:
从表中的主键引用了主表中的主键,所以需要在主键生成方式中设置成foreign,并将参数传进去,告诉hibernate应该使用哪一个主键。
好了,hibernate的一对一映射关系已经写完了
下一篇会说一下一对多关系的映射~