一對多,多對一關系映射


      一對多,多對一關系映射

  現實生活中有很多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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM