一对一
一对多(多对一)
多对多
就好像一个公民对应一个身份证号码,这是一对一的。这里就以公民-身份证为例。
这里涉及到两个注解:
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name=”pid”,unique=true)
这两个注解都写在我们的主控类当中,也可以理解为我们的主表类。
@OneToOne中的cascade表示的是级联关系,CascadeType.ALL表示的是全级联关系,包括级联删除、级联更新、级联添加等所有的级联关系。
@JoinColumn表示把我们的被控类的外键要写到我们的主控类当中。这里的pid就表示我们身份证类(被控类)当中的主键,就是那个身份证号码。unique=true表示是唯一的,pid将来在主表中充当的是外键,外键显然应该是唯一的。
注意:保存时应该先保存外键对象,再保存主表对象。
新建一个项目,建一个包,使用的还是Students类,不过稍微修改,配置文件也和之前一样。主控类是Students,还需要一个被控类IdCard类。
如下:
<hibernate-configuration>
<session-factory>
<property name="connection.username">rootproperty>
<property name="connection.password">12345678property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
property>
<property name="connection.url">
jdbc:mysql:///hibernate1?useUnicode=true&characterEncoding=UTF-8
property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
property>
<property name="show_sql">trueproperty>
<property name="format_sql">trueproperty>
<property name="hbm2ddl.auto">createproperty>
<property name="hibernate.current_session_context_class">threadproperty>
<mapping class="oto_fk.Students"/>
<mapping class="oto_fk.IdCard"/>
session-factory>
hibernate-configuration>
card是被控类的一个对象,所以在get方法上加上注解
@OneToOne(CascadeType.ALL)
@JoinColumn(name=”pid”,unique=true)
第一个注解中指定级联关系,第二个注解中name指定被控类的主键。
@Entity
public class Students {
private IdCard card;
private int sid;
private String gender;
private Date birthday;
private String major;
public Students(){
}
public Students(IdCard card, String gender, Date birthday,
String major) {
//super();
this.card = card;
this.gender = gender;
this.birthday = birthday;
this.major = major;
}
@Id
@GeneratedValue
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="pid")
public IdCard getCard() {
return card;
}
public void setCard(IdCard card) {
this.card = card;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
}
注意,构造方法中的sid可以不要,因为已经设置为自动增长类型的了。
被控类中加上@Entity注解将它映射成一个实体类,然后是指定主键属性,使用@Id。pid为String类型,所以使用主键生成器,并且指定长度。
//身份证类
@Entity
public class IdCard {
@Id
@GeneratedValue(generator="pid")
@GenericGenerator(name="pid",strategy="assigned")
@Column(length=18)
private String pid;//身份证号
private String sname;//学生姓名
public IdCard(){
}
public IdCard(String pid, String sname) {
super();
this.pid = pid;
this.sname = sname;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
}
这样一对一的单向外键关联关系就构建完成。
然后是测试类:
public class TestStudents {
@Test
public void testSchemaExport(){
//创建配置对象
Configuration config = new Configuration().configure();
//创建服务注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
//创建会话工厂对象
SessionFactory sessionFactory = config.buildSessionFactory(serviceRegistry);
SchemaExport export = new SchemaExport(config);
export.create(true,true);
}
}
之后会在数据库hibernate1中创建两个表pid和students。
然后在测试类中再创建一个方法来添加学生记录,保存主表对象之前要先保存外键的对象。
@Test
public void addStudents(){
//创建配置对象
Configuration config = new Configuration().configure();
//创建服务注册对象
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
//创建会话工厂对象
SessionFactory sessionFactory = config.buildSessionFactory(serviceRegistry);
//创建会话
Session session = sessionFactory.getCurrentSession();
//开启事务
Transaction tx = session.beginTransaction();
//先生成一个身份证对象
IdCard card = new IdCard("123456789123456789","某某人");
//再生成学生对象
Students s = new Students(card,"男",new Date(),"主修课程");
//先保存身份证类对象
session.save(card);
session.save(s);
//提交事务
tx.commit();
}
经测试可以成功添加记录