映射:一对一(人与身份)和多对多(老师对学生)
Posted 古兰精
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了映射:一对一(人与身份)和多对多(老师对学生)相关的知识,希望对你有一定的参考价值。
一、一对一:
第一种情况:IdCard类的ID 既是主键又是外键
package dao.po;
//人
public class Person {
private int id; //ID
private String name;//姓名
private IdCard idCard; //身份证(对象)
}
package dao.po;
//身份主类
public class IdCard{
private int id;//ID
private String address;//地址
private Person person; //身份证的主人
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="dao.po">
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
<property name="name" not-null="true" length="255" column="`name`"/>
<!-- 这里做一对一映射 -->
<!-- 没什么好说的,就是一 one-to-one -->
<one-to-one name="idCard" ></one-to-one>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="dao.po">
<class name="IdCard" table="id_card">
<id name="id">
<!-- 注意: -->
<!-- 本类的id 既是主键,又是外键 -->
<!-- IdCard对象的是从对象, Person是主对象, 先有主,后有从. -->
<generator class="foreign">
<!-- 此处的person是IdCard类的一个属性 -->
<param name="property">person</param>
</generator>
</id>
<property name="address" not-null="true" length="255" column="`address`"/>
<!-- 此处的person是IdCard类的一个属性 -->
<!-- constrained="true" 对生成的数据表产生约束,id_card表的id既是主键,又是外键 -->
<!-- constrained="false" 表结构上没有约束, 取何值对对象关系没影响,只是对表结构有影响-->
<one-to-one name="person" constrained="true"/>
</class>
</hibernate-mapping>
保存与查询:
package dao;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import dao.po.IdCard;
import dao.po.Person;
public class One2One{
public static void main(final String[] args){
add();
final IdCard c1 = query(5);
System.out.println(c1.getPerson().getName());
}
//保存
public static void add(){
final Person p1 = new Person();
p1.setName("小明");
final IdCard c1 = new IdCard();
c1.setAddress("北京市海淀区上地");
p1.setIdCard(c1); //建立关联(不能少)
c1.setPerson(p1); //建立关联(不能少)
Session session = null;
try{
session = HibernateUtil.getSeesion();
final Transaction tx = session.beginTransaction();
//session.save(p1); //
session.save(c1); //身份证是从对象依赖于主对象, "身份证"依赖于"人",
//保存 c1 , 也会自动保存 他依赖的p1,前题是c1 与p1要关联
tx.commit();
//SQL 如下:
//Hibernate: insert into Person (`name`) values (?)
//Hibernate: insert into id_card (`address`, id) values (?, ?)
//虽然只执行了session.save(c1) , 但有两个insert
}finally{
if (session != null){
session.close();
}
}
}
//查询 身份证
public static IdCard query(final int id){
Session session = null;
try{
session = HibernateUtil.getSeesion();
final IdCard c1 = (IdCard) session.get(IdCard.class, id);
Hibernate.initialize(c1.getPerson());
return c1;
//SQL 如下:
//Hibernate: select idcard0_.id as id3_0_, idcard0_.`address` as address2_3_0_ from id_card idcard0_ where idcard0_.id=?
//Hibernate: select person0_.id as id2_1_, person0_.`name` as name2_2_1_, idcard1_.id as id3_0_, idcard1_.`address` as address2_3_0_ from Person person0_ left outer join id_card idcard1_ on person0_.id=idcard1_.id where person0_.id=?
//注意person表又连了id-card表
}finally{
if (session != null){
session.close();
}
}
}
}
第二种情况:IdCard类的ID 只是主键, IdCard类多对一属性 person_id做 外键,指向Person类的主键。
这种情况有点像 多对一,关系如下图:
两个配置文件内容如下
二、多对多:
多对多由于在性能和操作都不大理想,所以使用很少。实际使用中最好转换为一对多的模型。Hibernate会为我们创建中间关联表,转换成两个一对多。
package dao.po;
import java.util.Set;
//学生类
public class Student{
private int id;
private String name;
private Set<Teacher> teachers;
}
package dao.po;
import java.util.Set;
//老师类
public class Teacher{
private int id;
private String name;
private Set<Student> students;
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="dao.po">
<class name="Student">
<id name="id">
<generator class="native"/>
</id>
<property name="name" not-null="true" length="255" column="`name`"/>
<!-- name="teachers" 表示:Student类中有一个属性叫teachers (是Set集合)-->
<!-- table="teacher_student" 表示:中间表表名叫teacher_student -->
<set name="teachers" table="teacher_student">
<!-- column="student_id" 表示:中间表teacher_student的字段-->
<!-- Student类的id与中间表teacher_student的字段student_id对应-->
<key column="student_id"/>
<!-- column="teacher_id" 表示:中间表teacher_student的字段-->
<!-- class="Teacher" 表示:中间表teacher_student的字段teacher_id与 Teacher类的id对应-->
<many-to-many class="Teacher" column="teacher_id"/>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="dao.po">
<class name="Teacher">
<id name="id">
<generator class="native"/>
</id>
<property name="name" not-null="true" length="255" column="`name`"/>
<set name="students" table="teacher_student">
<key column="teacher_id"/>
<many-to-many class="Student" column="student_id"/>
</set>
</class>
</hibernate-mapping>
保存操作:
package dao;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import dao.po.Student;
import dao.po.Teacher;
public class Many2Many {
public static void main(final String[] args){
add();
}
//添加几个老师与学生
public static void add(){
final Teacher t1 = new Teacher();
t1.setName("语文老师");
final Teacher t2 = new Teacher();
t2.setName("数学老师");
final Student s1 = new Student();
s1.setName("学生小明");
final Student s2 = new Student();
s2.setName("学生小红");
//final Set<Teacher> set_t = new HashSet<Teacher>();
//set_t.add(t1);
//set_t.add(t2);
final Set<Student> set_s = new HashSet<Student>();
set_s.add(s1);
set_s.add(s2);
//给老师set 学生
t1.setStudents(set_s); //建立关联,只在一方面建立关联就行了, 不可给学生set()了老师,再老师set()了学生
t2.setStudents(set_s); //建立关联,只在一方面建立关联就行了, 不可给学生建了关联,再老师建关联
//给学生set老师,不可以再做
Session session = null;
try{
session = HibernateUtil.getSeesion();
final Transaction tx = session.beginTransaction();
session.save(t1);
session.save(t2);
session.save(s1);
session.save(s2);
tx.commit();
}finally{
if (session != null){
session.close();
}
}
}
}
// 中间表teacher_student 表结构如下 :
//| teacher_student | CREATE TABLE `teacher_student` (
// `teacher_id` int(11) NOT NULL,
// `student_id` int(11) NOT NULL,
// PRIMARY KEY (`student_id`,`teacher_id`),
// KEY `FK2E2EF2DE4BF3A147` (`teacher_id`),
// KEY `FK2E2EF2DE3B5856A7` (`student_id`),
// CONSTRAINT `FK2E2EF2DE3B5856A7` FOREIGN KEY (`student_id`) REFERENCES `student
//` (`id`),
// CONSTRAINT `FK2E2EF2DE4BF3A147` FOREIGN KEY (`teacher_id`) REFERENCES `teacher
//` (`id`)
//) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
以上是关于映射:一对一(人与身份)和多对多(老师对学生)的主要内容,如果未能解决你的问题,请参考以下文章