以一对多的双向关联映射(Teacher——Student)作为实例
其Teacher类和Student类分别为:
package com.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Teacher {
private int id;
private String name;
private Set<Student> students = new HashSet<Student>();
@Id
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;
}
@OneToMany(mappedBy="teacher")
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
package com.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Student {
private int id;
private String name;
private Teacher teacher;
@Id
@GeneratedValue
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;
}
@ManyToOne
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
}
hibernate配置文件为:
<?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>
<!-- 连接的数据库驱动 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 连接的数据库的url -->
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
<!-- 连接的数据库的用户名-->
<property name="connection.username">root</property>
<!-- 连接的数据库的密码 -->
<property name="connection.password"></property>
<!-- 配置Hibernate数据库方言 -->
<property name="Dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 输出执行的SQL语句 -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- 启动时撤销并重新创建数据库的模式-->
<property name="hbm2ddl.auto">create</property>
<property name="current_session_context_class">thread</property>
<mapping class="com.model.Teacher"/>
<mapping class="com.model.Student"/>
</session-factory>
</hibernate-configuration>
建立其测试类,测试往Teacher表中添加数据,往Student表中添加数据,是否会自动外键关联
测试类:
package com.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.Test;
import com.model.Student;
import com.model.Teacher;
public class ORMappingTest {
@Test
public void test() {
Configuration cfg = new Configuration();
cfg.configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
SessionFactory sessionFactory = cfg.buildSessionFactory(serviceRegistry);
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Teacher t = new Teacher();
t.setName("t");
Student s = new Student();
s.setName("s");
session.save(t);
session.save(s);
transaction.commit();
sessionFactory.close();
}
}
测试结果:
Hibernate:
create table Student (
id integer not null auto_increment,
name varchar(255),
teacher_id integer,
primary key (id)
)
Hibernate:
create table Teacher (
id integer not null,
name varchar(255),
primary key (id)
)
Hibernate:
alter table Student
add index FKF3371A1B43F43EE8 (teacher_id),
add constraint FKF3371A1B43F43EE8
foreign key (teacher_id)
references Teacher (id)
23:28:32,368 INFO SchemaExport:405 - HHH000230: Schema export complete
Hibernate:
insert
into
Teacher
(name, id)
values
(?, ?)
Hibernate:
insert
into
Student
(name, teacher_id)
values
(?, ?)
查看表内容:
------------结果发现,在student表中的外键teacher_id没有关联到表teacher中------
-----要解决这个问题,有两种方法-----
方法1:测试时在student对象中存储teacher对象,并分别存储两个对象
Teacher t = new Teacher();
t.setName("t");
Student s = new Student();
s.setName("s");
s.setTeacher(t);
session.save(t);
session.save(s);
测试查看表内容为:
方法2:在Student类中注解@ManyToOne内声明属性值cascade={CascadeType.ALL}
@ManyToOne(cascade={CascadeType.ALL})
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
然后,测试类中设置:
Teacher t = new Teacher();
t.setName("t");
Student s = new Student();
s.setName("s");
s.setTeacher(t);
session.save(s);
------此方法在Student类中对Teacher的多对一关联映射中设置了级联,不需要存储对象teacher,在存储对象student时自动将其级联的teacher对象一起存储------
------结果同方法1相同
方法3:在Teacher类中注解@ManyToOne内声明属性值cascade={CascadeType.ALL},而Student类中注解@ManyToOne无任何属性值
@OneToMany(mappedBy="teacher",cascade={CascadeType.ALL})
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
然后,测试类中设置:
Teacher t = new Teacher();
t.setName("t");
Student s1 = new Student();
s1.setName("s1");
Student s2 = new Student();
s2.setName("s2");
t.getStudents().add(s1);
t.getStudents().add(s2);
s1.setTeacher(t);
s2.setTeacher(t);
session.save(t);
测试结果:
Hibernate:
create table Student (
id integer not null auto_increment,
name varchar(255),
teacher_id integer,
primary key (id)
)
Hibernate:
create table Teacher (
id integer not null,
name varchar(255),
primary key (id)
)
Hibernate:
alter table Student
add index FKF3371A1B43F43EE8 (teacher_id),
add constraint FKF3371A1B43F43EE8
foreign key (teacher_id)
references Teacher (id)
23:49:07,348 INFO SchemaExport:405 - HHH000230: Schema export complete
Hibernate:
insert
into
Teacher
(name, id)
values
(?, ?)
Hibernate:
insert
into
Student
(name, teacher_id)
values
(?, ?)
Hibernate:
insert
into
Student
(name, teacher_id)
values
(?, ?)
查看表:
------此方法在Teacher类中对Student的一对多关联映射中设置了级联,不需要存储对象student,在存储对象teacher时自动将其级联的student对象一起存储------
------此方法必须设置 s1.setTeacher(t);
s2.setTeacher(t);
否则student表外键不会关联到表teacher。
----------------------------------------------------------------------------
由此可见,在做关联关系表的CRUD时,需要考虑表的关系,方法1和2较简单也较常见。
-----------------cascade={CascadeType.ALL}只影响CRUD的C、U、D----------------