第五章 一对多关系

l          一对多的关系

在学生与班级对象模型中,通常多个学生实体对应一个班级,反过来,一个班级对应多个学生.

 

一对多的关系在数据库层面没有任何变动,还是两张表,学生表与班级表,学生表中有一个外键引用班级表的主键.

 

建立两张表students, myClass

students

CREATE TABLE `students` ( 

         `id` varchar(32) NOT NULL, 

         `name` varchar(20) default NULL, 

         `age` int(11) default NULL, 

         `birthday` date default NULL, 

         `class_id` varchar(32) default NULL, 

         PRIMARY KEY  (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

myClass

CREATE TABLE `myclass` ( 

         `id` varchar(32) NOT NULL default '', 

         `name` varchar(20) default NULL, 

         PRIMARY KEY  (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

Model: Student

public class Student {

     private String id;

     private Myclass myclass;

     private String name;

     private Integer age;

     private Date birthday;

 

     public Student() {

     }

 

     public Student(Myclass myclass, String name, Integer age, Date birthday) {

         this.myclass = myclass;

         this.name = name;

         this.age = age;

         this.birthday = birthday;

     }

 

     public String getId() {

         return this.id;

     }

 

     public void setId(String id) {

         this.id = id;

     }

 

     public Myclass getMyclass() {

         return this.myclass;

     }

 

     public void setMyclass(Myclass myclass) {

         this.myclass = myclass;

     }

 

     public String getName() {

         return this.name;

     }

 

     public void setName(String name) {

         this.name = name;

     }

 

     public Integer getAge() {

         return this.age;

     }

 

     public void setAge(Integer age) {

         this.age = age;

     }

 

     public Date getBirthday() {

         return this.birthday;

     }

 

     public void setBirthday(Date birthday) {

         this.birthday = birthday;

     }

}

Student.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="chapter2.model.Students" table="students">

        <id name="id" type="java.lang.String" column="id">

            <generator class="uuid.hex" />

        </id>       

        <property name="name" type="java.lang.String" column="name" />           

        <property name="age" type="java.lang.Integer" column="age" />          

        <property name="birthday" type="java.util.Date" column="birthday" />         

        <many-to-one name="myclass" class="chapter2.model.Myclass" column="class_id" />           

    </class>

</hibernate-mapping>

 

可以看到学生这一块和昨天讲的内容没有任何区别.唯一要变动的是班级这一块,一个班级中有多个学生,那么我们应该很自然的想到班级类中应该有一个集合类,能够容纳该班级所有的学生, 我们先看一下班级Model类的变动:

public class Myclass {

     private String id;

     private String name;

     // 看到这里,这里运用了一个set集合(set集合的特点:不能够存放相同的元素),这个集合能够容纳该班级下所有的学生.

     private Set<Student> students = new HashSet<Student>();

 

     public Myclass() {

     }

 

     public Myclass(String name) {

         this.name = name;

     }

 

     public String getId() {

         return this.id;

     }

 

     public void setId(String id) {

         this.id = id;

     }

 

     public String getName() {

         return this.name;

     }

 

     public void setName(String name) {

         this.name = name;

     }

 

     public Set<Student> getStudents() {

         return students;

     }

 

     public void setStudents(Set<Student> students) {

         this.students = students;

     }

}

 

那么接下来,我们在配置文件中应该怎么配置呢?因为我们要让这个集合能够找到该班级下所有的学生类.

 

Myclass.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="chapter2.model.Myclass" table="myclass">

        <id name="id" type="java.lang.String">

            <column name="id" length="32" />

            <generator class="uuid.hex"></generator>

        </id>

        <property name="name" type="java.lang.String">

            <column name="name" length="20" />

        </property>

        <set name="students">

            <key column="class_id" />

            <one-to-many class="chapter2.model.Student" />

        </set>

    </class>

</hibernate-mapping>

主要是这里:

<set name="studentses">

    <key column="class_id" />

    <one-to-many class="chapter2.model.Student" />

</set>

name属性指定班级类中集合的属性名, key标签的column属性要对应数据库中学生表中外键字段,因为Hibernate查询的时候要知道用自己的主键去匹配学生表中的哪个字段. one-to-many告诉set集合应该装什么类型的对象,也告诉了Hibernate应该查哪张表.

 

Dao:

MyclassDao

public class MyclassDao {

     public void create(Myclass myclass){

         Session session = null;

         try{

              session = HibernateUtil.getSession();

              session.beginTransaction();

              session.save(myclass);

              session.getTransaction().commit();

         }catch(RuntimeException re){

              session.getTransaction().rollback();

              throw re;

         }

     }

    

     public Myclass findById(Serializable s){

         Session session = null;

         Myclass myclass = null;

         try{

              session = HibernateUtil.getSession();

              session.beginTransaction();

              myclass = (Myclass) session.get(Myclass.class, s);

              session.getTransaction().commit();

         }catch(RuntimeException re){

              session.getTransaction().rollback();

              throw re;

         }

         return myclass;

     }

}

 

StudentDao

public class StudentDao {

     public void create(Student student) {

         Session session = null;

         try {

              session = HibernateUtil.getSession();

              session.beginTransaction();

              session.save(student);

              session.getTransaction().commit();

         } catch (RuntimeException re) {

              session.getTransaction().rollback();

              throw re;

         }

     }

}

 

测试类:

先运行方法向数据库中添加数据

public class Test {

     public static void main(String[] args) {      

         StudentDao studentDao = new StudentDao();

         MyclassDao myclassDao = new MyclassDao();

        

         Myclass myclass = new Myclass("java0801");

         Student student1 = new Student(myclass, "张三", 25, new Date());

         Student student2 = new Student(myclass, "李四", 25, new Date());

         Student student3 = new Student(myclass, "王五", 25, new Date());

         Student student4 = new Student(myclass, "赵六", 25, new Date());

         Student student5 = new Student(myclass, "林七", 25, new Date());

         Student student6 = new Student(myclass, "魏八", 25, new Date());

         myclassDao.create(myclass);

         studentDao.create(student1);    

         studentDao.create(student2);

         studentDao.create(student3);

         studentDao.create(student4);    

         studentDao.create(student5);

         studentDao.create(student6);

     }

}

 

接下来,我们测试一下,看能否通过班级找到所有的学生

public class Test {

     public static void main(String[] args) {      

         StudentDao studentDao = new StudentDao();

         MyclassDao myclassDao = new MyclassDao();

        

         Myclass myclass = myclassDao.findById("4028810027959bbc0127959bbd2f0001");

         try {

              Thread.sleep(5000);

         } catch (InterruptedException e) {

              e.printStackTrace();

         }

         Set<Student> students = myclass.getStudents();

         for(Student s : students){

              System.out.println(s.getName());

         }

     }

}

加入休眠, 是为了让大家看到一个延时提取的一个过程, 大家可以看下面

<set name="students" lazy="false">

     <key column="class_id" />

     <one-to-many class="chapter2.model.Student" />

</set>

set标签这里加了一个属性lazy="false",再运行上面的程序,看一下是什么效果

 

我们上面的示例是在创建学生的时候,告诉学生你属于哪个班级, 有时候会有新来的员工等待分配的情况,那这种情况怎么模拟呢?

public class Test {

     public static void main(String[] args) {      

         StudentDao studentDao = new StudentDao();

         MyclassDao myclassDao = new MyclassDao();

        

         //这里模拟新来的学生

         Student student1 = new Student("胶卷", 25, new Date());

         Student student2 = new Student("腾迅", 25, new Date());

         Student student3 = new Student("网易", 25, new Date());

         Student student4 = new Student("淘宝", 25, new Date());

         Student student5 = new Student("百度", 25, new Date());

         Student student6 = new Student("谷歌", 25, new Date());

         //新学生入库

         studentDao.create(student1);    

         studentDao.create(student2);

         studentDao.create(student3);

         studentDao.create(student4);    

         studentDao.create(student5);

         studentDao.create(student6);

        

         try {

              Thread.sleep(10000);

         } catch (InterruptedException e) {

              e.printStackTrace();

         }

 

         //学生打包

         Set<Student> students = new HashSet<Student>();

         students.add(student1);

         students.add(student2);

         students.add(student3);

         students.add(student4);

         students.add(student5);

         students.add(student6);

         //分配班级

         Myclass myclass = myclassDao.findById("4028810027959bbc0127959bbd2f0001");

         myclass.setStudents(students);

         //更新班级

         myclassDao.update(myclass);

     }

}

加入延时,是为了让大家看到这里,刚加入学生时,学生的外键是空的.

如果这样做,会将以前存在的数据中的外键更新为空.进一步证明了持久对象的特点, 在事务开始与结束之间,对象的任何变化都会在数据库中体现出来.

 

为了避免这种情况发生,我们可以更改为下面的代码:

public class Test {

     public static void main(String[] args) {      

         StudentDao studentDao = new StudentDao();

         MyclassDao myclassDao = new MyclassDao();

        

         //这里模拟新来的学生

         Student student1 = new Student("胶卷", 25, new Date());

         Student student2 = new Student("腾迅", 25, new Date());

         Student student3 = new Student("网易", 25, new Date());

         Student student4 = new Student("淘宝", 25, new Date());

         Student student5 = new Student("百度", 25, new Date());

         Student student6 = new Student("谷歌", 25, new Date());

         //新学生入库

         studentDao.create(student1);    

         studentDao.create(student2);

         studentDao.create(student3);

         studentDao.create(student4);    

         studentDao.create(student5);

         studentDao.create(student6);

        

         try {

              Thread.sleep(10000);

         } catch (InterruptedException e) {

              e.printStackTrace();

         }

 

         //分配班级

         Myclass myclass = myclassDao.findById("4028810027959bbc0127959bbd2f0001");

         //为了避免将原来学生的信息更新为空

         Set<Student> students = myclass.getStudents();

         students.add(student1);

         students.add(student2);

         students.add(student3);

         students.add(student4);

         students.add(student5);

         students.add(student6);

        

         //更新班级

         myclassDao.update(myclass);

     }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值