Hibernate-cascade级联-3

利用关联关系操作对象:
数据对象之间的关联关系有一对一,一对多及多对多三种。在数据库操作中,数据对象之间的关联关系使用JDBC处理很困难。例如,当删除一个班级的信息时,还要删除该班级的所有学生的基本信息。如果直接使用JDBC执行这种级联操作,会非常繁锁。Hibernate通过把实体对象之间的关联关系及级联关系在映射文件中声明,比较简单地解决了这类级联操作问题。
一对一关联关系的使用
一对一关联关系在实际生活中是比较觉的,例如学生与学生证的关系,通过学生证可以找到学生。一对一关联关系在Hibernate中的实现有两种方式,分别是主键关联和外键关联。
主键关联
主键关联的重点是,关联两个实体共享一个主键值。例如student与card是一对一关系,它们在数据库中对应的表分别是t_student和t_card。它们共用一个主键值ID,这个主键可由t_student或t_card表生成。问题是如何让另一张表引用已经生成的主键值呢?例如,t_student表未老先衰了ID的值,t_card表如何引用它?这需要在Hibernate的映射文件中使用主键的foreign生成机制!

为了表示Student与Card之间的一对一的关联关系,我们需要在它们各自的映射文件 中都要使用<one-to-one>标记!
一对一关系我在前面已经写过例子程序了,在这里仅给出两个映射文件。如下:
学生PO映射信息:

<? xml version="1.0" encoding="GBK" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

< hibernate-mapping >
     < class  name ="hibernate.PO.TStudent"  table ="t_student"  lazy ="true" > <!-- 把类与表关联起来  -->
         < id  name ="id"  type ="java.lang.Integer" >
             < column  name ="id" />
             < generator  class ="increment"   />
         </ id >
         < property  name ="userName"  type ="java.lang.String" >
             < column  name ="userName"  length ="20"   />
         </ property >
         < property  name ="cardId"  type ="java.lang.String" >
             < column  name ="card_id"  length ="20"   />
         </ property >
         < property  name ="sex"  type ="java.lang.String" >
             < column  name ="sex"  length ="2"   />
         </ property >
         < property  name ="age"  type ="java.lang.Integer" >
             < column  name ="age"   />
         </ property >
         < one-to-one  name ="card"  class ="hibernate.PO.TCard"  fetch ="join"  cascade ="all"   />
     </ class >
</ hibernate-mapping >
<!--
class元素的lazy属性设定为true,表示延迟加载,如果lazy设为false,则
表示立即加载。以下对这二点进行说明。
    立即加载:表示Hibernate在从数据库中取得数据组装好一个对象(如学生1)后,
            会立即再从数据库取得数据组装此对象所关联的对象(如学生证1)。
    延迟加载:表示Hibernate在从数据库中取得数据组装好一个对象(如学生1)后,
            不会立即再从数据库中取得数据组装此对象所关联的对象(如学生1),
            而是等到需要时,才会从数据库取得数据组装此关联对象。
<one-to-one>元素的cascade属性表明操作是否从父对象级联到被关联的对象,    它
的取得可以是以下几种:
    none:在保存,删除或修改当前对象时,不对其附属对象(关联对象)进行级联
          操作。它是默认值。
    save-update:在保存,更新当前对象时,级联保存,更新附属对象(临时对象,
          游离对象)。
    delete:在删除当前对象时,级联删除附属对象。
    all:所有情况下均进行级联操作,即包含save-update和delete操作。
    delete-orphan:删除和当前对象解除关系的附属对象。
<one-to-one>元素的fetch属性的可选值是join和select,默认是select。
当fetch属性设定为join时,表示连接抓取(Join fetching):Hibernate通过
在Select语句中使用outer join(外连接)来获得对象的关联实例或者关联集合。
当fetch属性设定为select时,表示查询抓取(Select fetching):需要另外发
送一条Select语句抓取当前对象的关联实体或集合。
-->


学生证PO映射信息:

<? xml version="1.0" encoding="GBK" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

< hibernate-mapping >
     < class  name ="hibernate.PO.TCard"  table ="t_card"  lazy ="true" >
         < id  name ="id"  type ="java.lang.Integer" >
             < column  name ="id" />
             < generator  class ="foreign" >
                 < param  name ="property" >student </ param >
             </ generator >
         </ id >
         <!--  id使用外键(foreign)生成机制,引用代号为student的对象
             的主键作为T_card表的主键和外键。同时student在下面的
             <one-to-one>中进行了定义 
-->
         < property  name ="name"  type ="java.lang.String" >
             < column  name ="name"  length ="20"   />
         </ property >
       
          
           < one-to-one  name ="student"  class ="hibernate.PO.TStudent"  constrained ="true"   />        
           <!--  constrained="true"表示Card引用了student的主键作为外键。  -->
     </ class >
</ hibernate-mapping >

 

外键关联
外键关联的要点是:两个实体各自有不同的主键,但其中一个实体有一个外键引用另一个实体的主键。例如,假设,Student和Card是外键关联的一对一关系们在数据库中相应的表分别如下:t_student表有一个主键ID,t_card表有一个主键ID和一个外键student_id,此外键对应t_student表的主键ID,那么student的映射信息如上面一样不做改动,而Card的映射文件要做相应的改动。如下:
< hibernate-mapping >
     < class  name ="hibernate.PO.TCard"  table ="t_card"  lazy ="true" >
         < id  name ="id"  type ="java.lang.Integer" >
             < column  name ="id" />
             < generator  class ="increment" /> <!--  不再是foreign了  -->                 
         </ id >
        
         < property  name ="name"  type ="java.lang.String" >
             < column  name ="name"  length ="20"   />
         </ property >
       
        < many-to-one  name ="student"  column ="student_id"  class ="hibernate.PO.TStudent"  unique ="true" />
        <!--  惟一的多对一,实际上变成一对一关系了  -->
          <!--  unique设为true表示使用DDL为外键字段生成一个惟一约束。
                 以外键关联对象的一对一关系,其本质上已经变成了一对多的双向关联,
                 应直接按照一对多和多对一的要求编写它们的映射文件。当unique为
                 true时实际上变成了一对一的关系。 
-->
           
     </ class >
</ hibernate-mapping >

一对多关联关系的使用
一对多关系很觉,例如班级与学生的关系就是典型的一对多的关系。在实际编写程序时,一对多关系有两种实现方式:单向关联和双向关联。单向的一对多关系只需要在一方进行映射配置,而双向的一对多需要在关联的双方进行映射配置。下面以Group(班级)和Student(学生)为例讲解如何配置一对多的关系。
单向关联
单向的一对多关系只需要在一方进行映射配置,所以我们只配置Group的映射文件:
< hibernate-mapping >
     < class  name ="hibernate.PO.Group"  table ="t_group"  lazy ="true" >
         < id  name ="id"  type ="java.lang.Integer" >
             < column  name ="id" />
             < generator  class ="increment" />                 
         </ id >
         <!--  insert属性表示被映射的字段是否出现在SQL的INSERT语句中  -->
         < property  name ="name"  type ="java.lang.String"  update ="true"  insert ="true" >
             < column  name ="name"  length ="20"   />
         </ property >
        
         <!--  set元素描述的字段对应的类型为java.util.Set类型。
            inverse用于表示双向关联中的被动一端。inverse的值
            为false的一方负责维护关联关系。
            sort排序关系,其可选值为:unsorted(不排序)。
                                  natural(自然排序)。
                                  comparatorClass(由某个实现了java.util.comparator接口的类型指定排序算法。)
            <key>子元素的column属性指定关联表(t_student表)的外键。
       
-->
         < set  name ="students"  
             table
="t_student"  
             lazy
="true"  
             inverse
="false"  
             cascade
="all"  
             sort
="unsorted" >
         < key  column ="ID" />
         < one-to-many  class ="hibernate.PO.TStudent" />        
         </ set >
     </ class >
</ hibernate-mapping >
双向关联
如果要设置一对多双向关联关系,那么还需要在“多”方的映射文件中使用<many-to-one>标记。例如,在Group与Student一对多的双向关联中,除了Group的映射文件外还需要在Student的映射文件中加入如下代码:
  < many-to-one  name ="group"
                     class
="Group"
                     cascade
="none"
                     outer-join
="auto"
                     update
="true"
                     insert
="true"
                     column
="ID"   />

inert和update设定是否对column属性指定的关联字段进行insert和update操作。
此外将Group.hbm.xml中<set>元素的inverse设置为true.

多对多关联关系的使用
Student(学生)和Course(课程)的关系就是多对多关系。在映射多对多关系时需要另外使用一个连接表(如Student_Course)。Student_Course表包含二个字段:courseID和studentID。此处它们的映射文件中使用<many-to-many>标记,在Student的映射文件中加入以下描述信息:

   < set  name ="courses"  
               table
="student_course"  
               lazy
="false"  
               inverse
="false"
               cascade
="save-update" >
                < key  column ="studentID"   />
            < many-to-many  class ="Course"  column ="CourseID" />    
            </ set >
相应的Course的映射文件中加入以下:
  < set  name ="students"  
               table
="student_course"  
               lazy
="false"  
               inverse
="true"
               cascade
="save-update" >
                < key  column ="CourseID"   />
            < many-to-many  class ="Student"  column ="StudentID" />    
            </ set >
添加关联关系
首先编写一个程序来看看一个名为Bill的学生选择了什么课程:
// 获取代表Bill的Student对象
        Student stu = (Student)session.createQuery("from Student s where s.name='Bill'").uniqueResult();
        List list =  new ArrayList(stu.getCourses());
         for( int i = 0 ; i < list.size(); i++)
         {
            Course course = (Course)list.get(i);//取得Course对象
            System.out.println(course.getName());//打印出Bill所选课程的清单
        }
现在Bill还想chemistry课程,这对于程序员来说只是为Bill添加一个到chemistry的关联,也就是说在student_course表中新增加一条记录,而T_student和T_Course表都不用变更。
// 获取代表Bill的Student对象
        Student stu = (Student)session.createQuery("from Student s where s.name='Bill'").uniqueResult();
        Course course = (Course)session.createQuery("from Course c where c.name='chemistry'").uniqueResult();
         // 设置stu与course的关联关系
        stu.getCourses().add(course);
        course.getStudents().add(stu);
删除关联关系
删除关联关系比较简单,直接调用对象集合的remove()方法删除不要的对象就可。例如:要从学生Bill的选课清单中删除politics和chemistry两门课,程序代码如下:
         // 获取代表Bill的Student对象
        Student stu = (Student)session.createQuery("from Student s where s.name='Bill'").uniqueResult();
        Course course1 = (Course)session.createQuery("from Course c where c.name='politics'").uniqueResult();
        Course course2 = (Course)session.createQuery("from Course c where c.name='chemistry'").uniqueResult();
        stu.getCourse().remove(course1); // 删除politics课程
        stu.getCourse().remove(course2); // 删除chemistry课程

运行以上程序将从student_course表中删除这两条记录,但T_student和T_course表没有任何变化.



Hibernate 表关系描述之OneToOne 用户和身份证号

在数据库领域中,数据表和数据表之间关系一般可以分为如下几种:
 单对单:比如公民和身份证的关系,一个人只有一张身份证,同时每张身份证也仅仅对应一个人!
 单对多:比如单个客户和订单之间的关系,每个客户可以同时下多张订单!
 多对多:比如学生管理系统中,学生与课程,教师与学生之间的关系!
 上面是简单的说了下数据库表与表之间的关系,那么我们现在要说的是Hibernate,来看看Hibernate中如何使用表与表的关系,首先来看看我数据库中二个示例表user和card分别表示用户和身份证!二个表中分别有二字段,创建表的DDL如下:
  create  table `study`.`card`(
        `cardid`  int  default  ''  not  null, -- 主键
       `cardnum`  int,     -- 身份证号
         primary  key (`cardid`)
    );
     create  unique  index ` PRIMARYon `study`.`card`(`cardid`);

         create  table `study`.` user`(
        `userid`  int  not  null auto_increment, -- 主键,自动递增
       `username`  varchar( 20), -- 用户名
         primary  key (`userid`)
    );
     create  unique  index ` PRIMARYon `study`.` user`(`userid`);

package fengyan.hibernate;



public class User  implements java.io.Serializable {


    // Fields    

     private Integer userid;
     private String username;

     private Card card;
     

    // Constructors

    public Card getCard() {
        return card;
    }



    public void setCard(Card card) {
        this.card = card;
    }



    /** default constructor */
    public User() {
    }


    
    /** full constructor */
    public User(String username) {
        this.username = username;
    }


   
    // Property accessors

    public Integer getUserid() {
        return this.userid;
    }

    
    public void setUserid(Integer userid) {
        this.userid = userid;
    }


    public String getUsername() {
        return this.username;
    }

    
    public void setUsername(String username) {
        this.username = username;
    }

}


package fengyan.hibernate;



public class Card  implements java.io.Serializable {


    // Fields    

     private Integer cardid;
     private Integer cardnum;
     private User user;
     

    // Constructors

    public User getUser() {
        return user;
    }



    public void setUser(User user) {
        this.user = user;
    }



    /** default constructor */
    public Card() {
    }


    
    /** full constructor */
    public Card(Integer cardnum) {
        this.cardnum = cardnum;
    }


   
    // Property accessors

    public Integer getCardid() {
        return this.cardid;
    }

    
    public void setCardid(Integer cardid) {
        this.cardid = cardid;
    }


    public Integer getCardnum() {
        return this.cardnum;
    }

    
    public void setCardnum(Integer cardnum) {
        this.cardnum = cardnum;
    }

}

我们现在就可以看到这样用户中有卡,卡也对应用户,一对一!在Bean中体现,当然现在我们已经要有概念,就是仅仅在Bean中这样声明是没用的,我们需要修改类与表的映射文件
 先改User.hbm.xml:内容如下:

<? xml version="1.0" encoding="GBK" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping >
     < class  name ="fengyan.hibernate.User"  table ="user" >
         < id  name ="userid"  type ="java.lang.Integer" >
             < column  name ="userid"   />
             < generator  class ="native"   /> <!--  主键为自动递增  -->
         </ id >
         < property  name ="username"  type ="java.lang.String" >
             < column  name ="username"  length ="20"   />
         </ property >
        
         <!--  
            我们添加一个<ont-to-one>节点 
            里面的属性card    对应的calss          
            cascade="all"一个用户对应一张卡,一张卡对应一个用户,但还是有一个主的,也就是人
            我们先出生人,然后才办卡,所以在这加入cascade由User主控                                                            
        
-->      
         < one-to-one  name ="card"  class ="fengyan.hibernate.Card"  cascade ="all" ></ one-to-one >
     </ class >
</ hibernate-mapping >

补充说明,cascade=all,说明当User删除或增加时Card也受影响!
Card.hbm.xml 内容如下:

<? xml version="1.0" encoding="GBK" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping >
     < class  name ="fengyan.hibernate.Card"  table ="card" >
         < id  name ="cardid"  type ="java.lang.Integer" >
             < column  name ="cardid"   />
             < generator  class ="foreign" > <!--  User是递增,那么卡的编号从哪来?  -->
                 < param  name ="property" >user </ param > <!-- 外键为user这个属性来确定 -->
             </ generator >
         </ id >
         < property  name ="cardnum"  type ="java.lang.Integer" >
             < column  name ="cardnum"   />
         </ property >
        
         < one-to-one  name ="user"  class ="fengyan.hibernate.User" ></ one-to-one >
     </ class >
</ hibernate-mapping >

配置完成后,我们来一编写一个DAO类userDAO.java代码如下:

package fengyan.hibernate;

import org.hibernate.Session;
import org.hibernate.Transaction;

public  class UserDAO  {

    public void save(User user)
    {
        
        Session session = HibernateSessionFactory.getSession();
        Transaction transaction = session.beginTransaction();
        session.save(user);
        transaction.commit();
        session.close();
    }

}

新建一个Servlet处理代码如下:

     public  void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException  {

        User user = new User();
        user.setUsername("fengyan");//设置用户名
        Card card = new Card();
        card.setCardnum(420983);//设置身份证号
        user.setCard(card);
        card.setUser(user);
        UserDAO ua = new UserDAO();
        ua.save(user);//这样在添加用户的时候会自动添加一张卡
    }

最后JSP代码:

   < body >
    This is my JSP page.  < br >
     < href ="servlet/addUser" >add user </ a >
   </ body >

当我们运行的时候,会发现User表中新增了一条记录

同时Card表中也新增了一条记录,但我们在doPost()方法中仅仅是save(user),而并没有save(card),为什么card也会添加进去,这就是我们在配置文件中写的表关系作用!


Hibernate 表关系描述之OneToMany

customer表:

create  table customers
(
    ID  bigint  not  null     primary  key auto_increment,
    userName  varchar( 20)
);
Order表:
create  table orders
(
    ID  bigint  not  null  primary  key auto_increment,
    customers_ID  bigint,     -- 应该为customers(ID)外键
    orderDescription  varchar( 50) -- 订单描述
);

客户表与订单表,来建立一个Project!~并且添加Hibernate~并由上面二张表生成Beans,主键都是native类型~自动递增!
我们将 自动生成的Customer.java    Bean添加一个SET属性,代码如下:


package fengyan.Hibernate;

import java.util.HashSet;
import java.util.Set;

/**
 *Authod:    fengyan
 *    date:    2006-12-30 01:02    
 
*/


public class Customers  implements java.io.Serializable {


    // Fields    

     private Long id;
     private String userName;

     //必须定义一个Set集合类型的属性以及它的get和set方法,
     
//它持有一个Customers对象所发出的所有订单的引用
     private Set orders = new HashSet();

    // Constructors

    public Set getOrders() {
        return orders;
    }



    public void setOrders(Set orders) {
        this.orders = orders;
    }



    /** default constructor */
    public Customers() {
    }


    
    /** full constructor */
    public Customers(String userName) {
        this.userName = userName;
    }


   
    // Property accessors

    public Long getId() {
        return this.id;
    }

    
    public void setId(Long id) {
        this.id = id;
    }


    public String getUserName() {
        return this.userName;
    }

    
    public void setUserName(String userName) {
        this.userName = userName;
    }


}


为Order.java   Bean 去掉cid(CustomerID)并添加一个Customer属性,代码如下:


package fengyan.Hibernate;
/**
 *Authod:    fengyan
 *    date:    2006-12-30 01:02    
 
*/


public class Orders  implements java.io.Serializable {


    // Fields    

     private Long id;
  //   private Long customersId;
     private String orderDescription;

     //添加一个Customers属性,用来引用一个订单对象所属的客户对象
     private Customers customer;
    // Constructors

    public Customers getCustomer() {
        return customer;
    }



    public void setCustomer(Customers customer) {
        this.customer = customer;
    }



    /** default constructor */
    public Orders() {
    }


    public Orders(String description)
    {
        this.orderDescription = description;
    }

   
    // Property accessors

    public Long getId() {
        return this.id;
    }

    
    public void setId(Long id) {
        this.id = id;
    }


   
    public String getOrderDescription() {
        return this.orderDescription;
    }

    
    public void setOrderDescription(String orderDescription) {
        this.orderDescription = orderDescription;
    }

}

 


修改Customer.hbm.xml映射文件:

<? xml version="1.0" encoding="GBK" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

< hibernate-mapping >
     < class  name ="fengyan.Hibernate.Customers"  table ="customers"  catalog ="study" >
         < id  name ="id"  type ="java.lang.Long" >
             < column  name ="ID"   />
             < generator  class ="native"   />
         </ id >
         < property  name ="userName"  type ="java.lang.String" >
             < column  name ="userName"  length ="20"   />
         </ property >
        
         <!--  name集合属性orders    
             table对应的表名    
             cascade 级联关系,当保存或更新时会级联保存与这个Customers对象相关联的所有Orders对象
             inverse=true是将 控权抛出(给Orders) 
-->
         < set  name ="orders"  table ="orders"  cascade ="save-update"  inverse ="true" >
             < key  column ="customers_ID" ></ key > <!--  表字段  -->        
             < one-to-many  class ="fengyan.Hibernate.Orders" /> <!--  关联的类  -->
         </ set >
     </ class >
</ hibernate-mapping >


修改Order.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 ="fengyan.Hibernate.Orders"  table ="orders"  catalog ="study" >
         < id  name ="id"  type ="java.lang.Long" >
             < column  name ="ID"   />
             < generator  class ="native"   />
         </ id >
       
         < property  name ="orderDescription"  type ="java.lang.String" >
             < column  name ="orderDescription"  length ="50"   />
         </ property >
        
         <!--  name属性名
             class对应的类
             column对应的表字段 
-->
         < many-to-one  name ="customer"  class ="fengyan.Hibernate.Customers"  column ="customers_ID" ></ many-to-one >
     </ class >
</ hibernate-mapping >

然后我们建立一个CustomersDAO操作类

package fengyan.Hibernate;

import org.hibernate.Session;
import org.hibernate.Transaction;

public  class CustomersDAO  {
    
    public void save(Customers customer)
    {
        Session session = HibernateSessionFactory.getSession();//会话
        try
        {
            Transaction tx = session.beginTransaction();//事物
            session.save(customer);//保存
            tx.commit();//提交事物
        }

        catch(Exception e)
        {
            System.out.println("DAO has Errors:"+e);
        }

        finally
        {
            session.close();//关闭会话
        }

    }


}

再来建立一个Servlet     MyServlet.java代码如下:

package fengyan.Hibernate;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public  class MyServlet  extends HttpServlet  {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //声明一个用户
        Customers customer = new Customers("fengyan");
        
        //声明二订单
        Orders order1 = new Orders("描述1");
        Orders order2 = new Orders("描述2");
        
        //订单关联用户
        order1.setCustomer(customer);
        order2.setCustomer(customer);
        
        //用户关联订单
        customer.getOrders().add(order1);
        customer.getOrders().add(order2);
        
        //save
        CustomersDAO cd = new CustomersDAO();
        cd.save(customer);//我们仅仅保存了Customers!
        
    }

}
为什么Hibernate会自动帮我们将订单也添加到表中呢,就是我们在Customers.hbm.xml映射配置中,set节点的cascade=save-update,就是当我们保存或更新Customers的时候也会自动保存相应的Orders对象!


Hibernate 表关系描述之ManyToMany

create  table teachers
(
    teaID  bigint auto_increment  primary  key,
    teaName  varchar( 20)
);

create  table students
(
    stuID  bigint  primary  key auto_increment,
    sName  varchar( 20)
);

-- 关联表   学生与教师
create  table student_teacher_table
(
    teaID  int,
    stuID  int
);
Step2:新建一个HibernateManyToMany项目 ,并添加hibernate。
Step3:我们将前面创建的teachers表和students表导向到Beans中,注意这里的关系表 student_teacher_table并不导出!因为我们数据做持久,持久的是对象,而不是关系, student_teacher_table表存放的是关系,所以我们不需要将 其导出,那么使用呢?接着看吧!
Step4:现在我们开始类对象关系的描述,我们先打开生成的Student.java 在里面添加Set 教师集合,然后在Teachers.java中同样添加Set学生集合!
Step5:我们描述了类与类之间的关系后,剩下的就是让Hibernate知道它们之间的关系,分别修改学生和教师类映射文件!
student.hbm.xml内容如下:
<? xml version="1.0" encoding="GBK" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
   Autho:fengyan
   date: 2006-12-30 17:04
-->
< hibernate-mapping >
     < class  name ="hibernate.beans.Students"  table ="students"  catalog ="study" >
         < id  name ="stuId"  type ="java.lang.Long" >
             < column  name ="stuID"   />
             < generator  class ="native"   />
         </ id >
         < property  name ="sname"  type ="java.lang.String" >
             < column  name ="sName"  length ="20"   />
         </ property >
        
         < set  name ="teachers"  table ="student_teacher_table"  cascade ="save-update"  inverse ="false" >
            
             < key  column ="stuID" ></ key >
             <!--
            它的控制主要是通过stuid来选择,就是我们从student_teacher_table表中我们只
            要select *  from student_teacher_table where  stuID='该学生ID',这样我
            们就可以获取它的教师的ID了
             
-->
         
              < many-to-many  class ="hibernate.beans.Teachers"  column ="teaID" ></ many-to-many >
              <!--  
             我们从student_teacher_table表中根据stuID拿到了与该stuID关联的teaID,
             然后 select * from teacher where teaID='前一步拿到的teaID' 
-->
         </ set >
     </ class >
</ hibernate-mapping >

再看teacher.hbm.xml文件内容:
<? xml version="1.0" encoding="GBK" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
   Authod:fengyan
   date:  2006-12-30 17:10
-->
< hibernate-mapping >
     < class  name ="hibernate.beans.Teachers"  table ="teachers"  catalog ="study" >
         < id  name ="teaId"  type ="java.lang.Long" >
             < column  name ="teaID"   />
             < generator  class ="native"   />
         </ id >
         < property  name ="teaName"  type ="java.lang.String" >
             < column  name ="teaName"  length ="20"   />
         </ property >
        
         <!--  前面在student中已经级联了,所以这里我没有再级联,简单的演示!  -->
         < set  name ="students"  table ="student_teacher_table"  inverse ="true" >
             < key  column ="teaID" ></ key >
             < many-to-many  class ="hibernate.beans.Students"  column ="stuID" ></ many-to-many >
         </ set >
     </ class >
</ hibernate-mapping >

然后我们现在建立一个StudentDAO.java用来封装操作:

package hibernateDAOS;
/**
 * Authod:fengyan
 * date:   2006-12-30 17:15    
 
*/

import hibernate.HibernateSessionFactory;
import hibernate.beans.Students;

import org.hibernate.Session;
import org.hibernate.Transaction;

public class StudentsDAO {
    public void save(Students student)
    {
        Session session = HibernateSessionFactory.getSession();        
        Transaction tx = session.beginTransaction();
        try
        {
            session.save(student);
            tx.commit();
        }

        catch(Exception e)
        {
            System.out.println("stuDAO has errors:"+e);
            tx.rollback();
        }

        finally
        {
            session.close();
        }

    }


}

Step6:建立一个Servlet,MyServlet.java;

package hibernate.servlet;

import hibernate.beans.Students;
import hibernate.beans.Teachers;
import hibernateDAOS.StudentsDAO;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //产生学生
        Students s1 = new Students("学生1");
        Students s2 = new Students("学生2");
        
        //产生教师
        Teachers t1 = new Teachers("教师1");
        Teachers t2 = new Teachers("教师2");
        Teachers t3 = new Teachers("教师3");
        Teachers t4 = new Teachers("教师4");
        
        //学生关联教师(学生选择教师)
        s1.getTeachers().add(t1);
        s1.getTeachers().add(t2);
        //学生 s1 选择 t1 及 t2 二名教师

        s2.getTeachers().add(t1);
        s2.getTeachers().add(t3);
        //学生 s2 选择 t1 及 t3 二名教师
        
        
//我们保存学生 s1及 s2
        StudentsDAO sd = new StudentsDAO();
        sd.save(s1);
        sd.save(s2);
    }

}

Step7:最后来个测试index.jsp页面
< href ="servlet/MyServlet" >add  </ a >

运行 结果:



由图片可知,
第一步:首先将 “学生1”插入students表中;
第二步:将"学生1"关联的“教师1”插入到teachers表中;
第三步:将“学生1”关联的“教师2”插入到teachers表中;
第四步:将“学生1”与“教师1”的关联信息(1,1)插入到student_teacher_table表中;
第五步:将“学生1”与“教师2”的关联信息(1,2)插入到student_teacher_table表中;
第六步:将“学生2”插入students表中;
第七步:将“教师3”插入teachers表中;
第八步:更新?更新了“学生2”关联~这步有点不解
第九步:将“学生2”与“教师1”的关联信息(2,1)插入到student_teacher_table表中;
第十步:将“学生2”与“教师3”的关联信息(2,3)插入student_teacher_table表中;

转载于http://www.cnblogs.com/eflylab/archive/2006/12/30/608163.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值