hibernate-关系映射

来源:互联网 发布:mac 静音无法勾选 编辑:程序博客网 时间:2024/06/01 08:56

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 (?, ?)
原创粉丝点击