zoukankan      html  css  js  c++  java
  • 一对多,多对一关系映射

          一对多,多对一关系映射

      现实生活中有很多1对多(多对1)的关系模型。比如,一个人可以有0到多套房子,0到多辆汽车;一个父亲有0到多个孩子等等。这种关系被称作1对多关系。反过来,房子与人,汽车与人的关系,以及孩子与父亲的关系就是多对一的关系。这里需要注意一点的是,多对一关系的一个前提是:一套确定的房子只能属于某个确定的人(不能属于多人);一个确定的孩子也只能属于某个确定的父亲。

      下面我们就拿最简单的父亲和孩子的关系来说明1对多(多对1)模型的映射。

    关系模型:父亲 vs 孩子(Father vs Son)。
    关系映射:one-to-many

    反过来,

    关系模型:孩子 vs 父亲(Son vs Father)。
    关系映射:many-to-one


      很多初学者往往有这样的疑问,我什么时候需要定义映射关系呢?

      答案很简单:按需求来确定。就是说你需要哪种关系的时候就定义哪种映射,不需要的时候就可以不定义它们的关系映射了。还是以上面的例子来说明。

      如果你需要在取得孩子(Son)的时候,同时需要知道该孩子的父亲(Father)是谁,你就可以在孩子的实体类里定义孩子跟父亲的关系映射: @ManyToOne 。
    同样,如果需要知道某父亲的所有孩子,就可以在父亲的实体类里定义父亲跟孩子的关系映射: @OneToMany 。

    1.ManyToOne(多对一)

      单向:不产生中间表,但可以用@Joincolumn(name=" ")来指定生成外键的名字,外键在多的一方表中产生!
    2.OneToMany(一对多

      单向:会产生中间表,此时可以用@onetoMany @Joincolumn(name=" ")避免产生中间表,并且指定了外键的名字(别看 @joincolumn在一中写着,但它存在在多的那个表中)
    3.OneToMany ,ManyToOne 双向

      两个注解一起用的):如果不在 @OneToMany 中加mappedy属性就会产生中间表,此时通常在 @ManyToOne 的注 解下再添上注解 @Joincolumn(name=" ") 来指定外键的名字(说明:多的一方为关系维护端,关系维护端负责外键记录的更新,关系被维护端没有权利更新 外键记录)!( @OneToMany(mappedBy="一对多中,多中一的属性") 出现mapby为被维护端|||默认为延迟加载)

    用例:

    1 @ManyToOne(fetch=FetchType.LAZY)
    2 @JoinColumn(name="child_id")
    3 private OrderChild orderChild;
    4 
    5 @OneToMany(mappedBy="orderChild",fetch=FetchType.LAZY,cascade={CascadeType.MERGE})
    6 @NotFound(action=NotFoundAction.IGNORE)//代表可以为空,允许为null
    7 private List<OrderChildGoods> goodsList;

      hibernate中@ManyToOne默认是立即加载,@OneToMany默认是懒加载
    但是如果加上了@NotFound之后设置的fetch=FetchType.LAZY是不起作用的,也就是设置@NotFound后变为了立即加载eager

      下面举例详细说明一下

    @ManyToOne 
      @ManyToOne注解的这端,是多端

      1.在注释@ManyToOne(cascade=CascadeType.REFRESH,optional=true)中将属性optional设置为true,这可以使得即使外键为空时仍可以向表中添加数据。

      2.假设Person和Book是一对多的关系,其中Person的成员变量为:

    1 private Integer personId;
    2 private String name;
    3 private Short age;
    4 private List<Book> bookList=new ArrayList<Book>();

      对应在MySql中表的结构为:Person(personId,name,age),不必有bookList一项,在getBookList上方通过注释: 

    1 @OneToMany(mappedBy="person",cascade=CascadeType.ALL)
    2 @OrderBy(value="bookId ASC")

     与Book关系形成一对多的关系。

      Book的成员变量是:

    1 private int bookId;
    2 private String title;
    3 private double price;
    4 private Person person;

      对应在MySql中表的结构为:Book(bookId,title,price,personId),注意要有Person表的主键personId,这样在插入记录时才不会产生异常。在getPerson上方有注释:

    1 @ManyToOne(cascade=CascadeType.REFRESH,optional=true)
    2 @JoinColumn(name="personId")

    与@OneToMany形成呼应。


      在EJB3.0 规范中 多对一与一对多的双向关系, 多对一(就是 @ManyToOne 注解的这端,是多端哦不要搞混了)这端总是双向关联端的主题(owner)端, 而一对多端的关联注解为  @OneToMany(mappedBy=" " ) 其值是:多对一端的属性


      demo:
      被动方:其实也就是一方 或者说(OneToMany方)

     1 @Entity
     2 public class Customer extends AbstractEntity {
     3 private String name;
     4 
     5 @OneToMany(mappedBy="customer",cascade=CascadeType.ALL)
     6 private Set<Order> orders;
     7 public void addOrder(Order order){
     8          if(orders == null){
     9               orders = new HashSet<Order>();
    10             }
    11       orders.add(order);
    12     }
    13 
    14   public String getName() {
    15       return name;
    16      }
    17   public void setName(String name) {
    18       this.name = name;
    19      }
    20   public Set<Order> getOrders() {
    21       return orders;
    22      }
    23   public void setOrders(Set<Order> orders) {
    24         this.orders = orders;
    25       }
    26 
    27   }

    主动方:1.关系的维护方2.ManyToOne方3.多方

     1 @Entity
     2 @Table(name="orders")
     3 public class Order extends AbstractEntity {
     4 private String name;
     5 
     6 @ManyToOne(cascade=CascadeType.ALL)
     7 private Customer customer;
     8 
     9 
    10 public Customer getCustomer() {
    11         return customer;
    12           }
    13 public void setCustomer(Customer customer) {
    14         this.customer = customer;
    15           }
    16 public String getName() {
    17        return name;
    18           }
    19 public void setName(String name) {
    20        this.name = name;
    21           }
    22    }

      以上是实体

    下面是测试用列哦

     1 public void testCRUD() {
     2 // 第一种情况: 调用的被动方的Dao 绑定主动方关系,但主动方没有绑定被动方
     3   Customer entity = new Customer();
     4   entity.setName("customer1");
     5   Order order = new Order();
     6   order.setName("order1");
     7   entity.addOrder(order);
     8   entity = customerDao.create(entity); // 这种情况下 orders.customer_id == null
     9   //控制台的信息
    10   //Hibernate: insert into Customer (name, id) values (?, ?)
    11   //这里的customer_id 为null
    12   //Hibernate: insert into orders (name, customer_id, id) values (?, ?, ?)
    13   System.out.println("entity id = " + entity.getId());
    14   System.out.println("order id = "+ order.getId());
    15   System.out.println("1111********************** over");
    16 
    17   // 第二种情况: 调用的被动方的Dao 绑定主动方关系,并且主动方也绑定被动方
    18   entity = new Customer();
    19   entity.setName("customer2");
    20   order = new Order();
    21   order.setName("order2");
    22   entity.addOrder(order);
    23   order.setCustomer(entity); //这里进行双向关联
    24   entity = customerDao.create(entity);
    25   //
    26   //Hibernate: insert into Customer (name, id) values (?, ?)
    27   //这里的customer_id 有值哦
    28   //Hibernate: insert into orders (name, customer_id, id) values (?, ?, ?)
    29   System.out.println("entity id = " + entity.getId());
    30   System.out.println("order id = "+ order.getId());
    31   System.out.println("2222********************** over");
    32   // 第三种情况: 调用的主动方的Dao 绑定被动方关系,但是被东方不绑定主动方
    33   entity = new Customer();
    34   entity.setName("customer3");
    35   order = new Order();
    36   order.setName("order3");
    37   order.setCustomer(entity); //绑定被动方
    38   orderDao.create(order);
    39   //Hibernate: insert into Customer (name, id) values (?, ?)
    40   //Hibernate: insert into orders (name, customer_id, id) values (?, ?, ?)
    41   System.out.println("entity id = " + entity.getId());
    42   System.out.println("order id = "+ order.getId());
    43   System.out.println("3333********************** over");
    44 
    45   // 第四种情况: 调用的主动方的Dao 绑定被动方关系,并且被东方也绑定主动方
    46   entity = new Customer();
    47   entity.setName("customer4");
    48   order = new Order();
    49   order.setName("order4");
    50   order.setCustomer(entity); //绑定被动方
    51   orderDao.create(order);
    52   System.out.println("entity id = " + entity.getId());
    53   System.out.println("order id = "+ order.getId());
    54   System.out.println("4444********************** over");
    55   //Hibernate: insert into Customer (name, id) values (?, ?)
    56   //Hibernate: insert into orders (name, customer_id, id) values (?, ?, ?)
    57 
    58   //总结:经测验二三四种方法结果都是一样都能持久化到数据库,并且关系也建立好了
    59   // 也就说只要主动方绑定了被动方关系就维护好了
    60    }
    61 *****************************************做级联删除测试************************************************************
    62   public void testCascade(){
    63 
    64   //1. 做个级联删除吧 测试删除主动方是否删除关联方
    65   // 这里会级联删除主动方的关联对象,以及该关联对象(被动方)所关联的所有主动方都会被级联删除
    66   orderDao.delete("order_id_1");
    67   //Hibernate: delete from orders where id=?
    68   // Hibernate: delete from orders where id=?
    69   // Hibernate: delete from orders where id=?
    70   // Hibernate: delete from orders where id=?
    71   // Hibernate: delete from orders where id=?
    72   // Hibernate: delete from Customer where id=?
    73   assertNull( orderDao.findById("orderDao"));
    74 
    75   //2. 做个级联删除吧 测试删除被动方是否删除关联方
    76   //删除该被动方,以及所关联的所有主动方(维护关系方or多方)与上面的调用主动方的结果一样
    77   //Hibernate: delete from orders where id=?
    78   // Hibernate: delete from orders where id=?
    79   // Hibernate: delete from orders where id=?
    80   // Hibernate: delete from orders where id=?
    81   // Hibernate: delete from orders where id=?
    82   // Hibernate: delete from Customer where id=?
    83   customerDao.delete("2");
    84   assertNull( customerDao.findById("2"));
    85 
    86   }

    参考:http://blog.csdn.net/daryl715/article/details/1886892

         http://blog.csdn.net/jackieliulixi/article/details/19043753

         http://blog.csdn.net/xiaodaiye/article/details/51118870

         http://blog.csdn.net/xiaodaiye/article/details/51118870

  • 相关阅读:
    CCS
    CCS
    CCS
    CCS
    CCS
    CCS
    CCS
    CCS
    Java之内部类
    Java之回调模式和ThreadLocal
  • 原文地址:https://www.cnblogs.com/jin-zhe/p/8269635.html
Copyright © 2011-2022 走看看