hibernate-关系映射

Hibernate的关联关系映射

三种实体关系分别是:

  • 一对多:在多的一方,添加一的一方的主键作为外键
  • 多对多:产生中间关系表,引入两张表的主键作为外键,两个主键称为联合主键。
  • 一对一:在任意一方引入对方主键作为外键(开发中使用非常少,基本都合成一张表了)

一对多关联关系映射

双向关联

一对多映射关系是由“多”的一方指向“一”的一方。在表示“多”的一方数据表中增加一个外键,来指向“一”的一方的数据表,“一”的一方作为主表,而“多”的一方作为从表。

一个客户可以有多个订单。

public class Customer{
  private Integer id;
  private String name;
  private Set<Order> orders=new HashSet<Order>();//用户有多个订单
  //这里省略了get,set方法
  ...
}
public class Order {
    private Integer id;
    private String address;
    private Double price;
    private Customer customer;//订单属于某一个用户
    //这里省略了get,set方法
    ...
}

Order.hbm.xml

<!--多对一关系映射-->
<many-to-one name="customer" class="cn.eaglezsx.Customer" column="cid"/>

name属性用来描述customer在Order类中的属性的名称,class属性用来指定映射的类,column属性值对应表中的外键列名,可以任意取名。

Customer.hbm.xml

<!--一对多关系映射-->
<set name="orders">
    <key column="cid"/>
    <one-to-many class="cn.eaglezsx.Order"/>
</set>
public class OneToManyTest{
  @Test
  public void test(){

    ...

    //1.创建一个客户
    Customer c=new Customer();
    c.setName("张三");

    //2.创建两个订单
    Order o1=new Order();
    o1.setAddress("北京");
    o1.setPrice("1000d");
    Order o2=new Order();
    o2.setAddress("广州");
    o2.setPrice(800d);

    //3.描述关系---订单属于某个客户
    o1.setCustomer(c);
    o2.setCustomer(c);

    //4.描述关系---客户有多个订单
    c.getOrders().add(o1);
    c.getOrders().add(o2);

    //5.先存客户再存订单
    session.save(c);
    session.save(o1);
    session.save(o2);

    ...

  }
}

运行程序,控制台输出的SQL语句为

Hibernate: insert into customer (name) values (?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)
Hibernate: update orders set cid=? where id=?
Hibernate: update orders set cid=? where id=?

三条insert语句,两条update语句。后两条insert语句已经对cid进行设置了,后边的update又设置了一遍。

使用双向关联会执行两遍SQL语句,比较浪费资源。

单向关联

删除Order类中的Customer字段,Order.hbm.xml中配置的信息,测试类中的o1.setCustomer(c);和 o2.setCustomer(c);。

运行程序,控制台的打印信息为

Hibernate: insert into customer (name) values (?)
Hibernate: insert into orders (address, price) values (?, ?)
Hibernate: insert into orders (address, price) values (?, ?)
Hibernate: update orders set cid=? where id=?
Hibernate: update orders set cid=? where id=?

后两个insert语句不再对cid进行操作。

或者删除Customer类中的orders字段,Customer.hbm.xml中配置的信息,测试类中的c.getOrders().add(o1);和c.getOrders().add(o2);。

运行程序,控制台的打印信息为

Hibernate: insert into customer (name) values (?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)

只有三个insert语句,没有update语句。

反转操作

如果还是用双向关联,但不想产生多余的SQL语句,可以在配置文件中设置一下让一方放弃对关联关系的控制。

在一对多关系中,会将一的一方的inverse属性设置为true,即由多的一方来维护关系。

在Customer.hbm.xml文件中,给set元素添加inverse属性,设置为true。该属性默认值false,两端都能控制关系。

<set name="orders" inverse="true">
    <key column="cid"/>
    <one-to-many class="cn.itcast.hibernate3.demo1.Order"/>
</set>

测试类中的c.getOrders().add(o1);和c.getOrders().add(o2);也可以删除了。

运行程序,控制台的打印信息为

Hibernate: insert into customer (name) values (?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)
Hibernate: insert into orders (address, price, cid) values (?, ?, ?)

在一对多关系中inverse只能设置在一的一方,many-to-one元素没有此属性。

级联操作

级联操作是指当主控方执行保存、更新或者删除操作时,其关联对象(被控方)也执行相同的操作。

更改Customer.hbm.xml,给set元素添加cascade属性

<set name="orders" cascade="save-update">
    <key column="cid">
    <one-to-many class="cn.eaglezsx.Order"/>
</set>

这时可以删除session.save(o1);和session.save(o2);这两句话。保存客户的时候也会把订单保存了。

  • save-update:在执行save、update或saveOrUpdate时进行关联操作。
  • delete:在执行delete时进行关联操作
  • delete-orphan
  • all
  • all-delete-orphan
  • none

级联操作:简化操作,目的就是为了少写两行代码(不用也行)。用的话可以用save-update,不建议使用delete

级联操作可以设置在一的一方也可以设置在多的一方。在多对多中,不用使用delete,比如我把课程删了,对应的学生也会被删除,这样不合逻辑。

多对多关联关系映射

学生和课程之间存在多对多的关系。

Student.java

public class Student {
    private Integer id;
    private String sname;
    private Set<Course> courses=new HashSet<Course>();
    //此处省略get和set方法
    ...
}

Course.java

public class Course {
    private Integer id;
    private String cname;
    private Set<Student> students=new HashSet<Student>();
    //此处省略get和set方法
    ...
}

Student.hbm.xml

<set name="courses" table="s_c">
    <key column="sid"/>
    <many-to-many class="cn.itcast.hibernate3.demo1.Course" column="cid"/>
</set> 

set元素多了个table属性,这个属性表示中间表的名称。key标签的column属性用于描述student表在中间表中的外键列名称。many-to-many标签中的column属性描述course课程表在中间表中的列名。

Course.hbm.xml

<set name="students" table="s_c">
    <key column="cid"/>
    <many-to-many class="cn.itcast.hibernate3.demo1.Student" column="sid"/>
</set> 

ManyToManyTest.java

public class ManyToManyTest {

    @Test
    public void test(){

        ...

        //1.创建两个学生
        Student s1=new Student();
        s1.setSname("张三");
        Student s2=new Student();
        s2.setSname("李四");

        //2.创建两个科目
        Course c1=new Course();
        c1.setCname("Java");
        Course c2=new Course();
        c2.setCname("C#");

        //3.建立关联关系
        //学生关联科目
        s1.getCourses().add(c1);
        s2.getCourses().add(c1);
        s1.getCourses().add(c2);
        s2.getCourses().add(c2);

        //4.存储
        session.save(c1);
        session.save(c2);
        session.save(s1);
        session.save(s2);

        ...

    }
}

运行程序,控制台输出

Hibernate: insert into course (cname) values (?)
Hibernate: insert into course (cname) values (?)
Hibernate: insert into student (sname) values (?)
Hibernate: insert into student (sname) values (?)
Hibernate: insert into s_c (sid, cid) values (?, ?)
Hibernate: insert into s_c (sid, cid) values (?, ?)
Hibernate: insert into s_c (sid, cid) values (?, ?)
Hibernate: insert into s_c (sid, cid) values (?, ?)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值