在领域模型中,类与类之间最普通的关系就是关联关系。
在UML中,关联是有方向的:
例如:Customer与Order,一个用户能发出多个订单,而一个订单只能属于一个用户。
- 单向关联
1)从Order到Customer的关联是多对一关联;
定义Customer:
1 package com.dx.hibernate.onetomany; 2 3 public class Customer { 4 private Integer customerId; 5 private String customerName; 6 7 public Customer() { 8 } 9 10 public Customer(String customerName) { 11 super(); 12 this.customerName = customerName; 13 } 14 15 public Integer getCustomerId() { 16 return customerId; 17 } 18 19 public void setCustomerId(Integer customerId) { 20 this.customerId = customerId; 21 } 22 23 public String getCustomerName() { 24 return customerName; 25 } 26 27 public void setCustomerName(String customerName) { 28 this.customerName = customerName; 29 } 30 }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2017-5-24 12:02:56 by Hibernate Tools 3.5.0.Final --> <hibernate-mapping> <class name="com.dx.hibernate.onetomany.Customer" table="CUSTOMER"> <id name="customerId" type="java.lang.Integer"> <column name="CUSTOMER_ID" /> <generator class="native" /> </id> <property name="customerName" type="java.lang.String"> <column name="CUSTOMER_NAME" /> </property> </class> </hibernate-mapping>
定义Order:
package com.dx.hibernate.onetomany; public class Order { private Integer orderId; private String orderName; private Customer customer; public Integer getOrderId() { return orderId; } public void setOrderId(Integer orderId) { this.orderId = orderId; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2017-5-24 12:02:56 by Hibernate Tools 3.5.0.Final --> <hibernate-mapping> <class name="com.dx.hibernate.onetomany.Order" table="ORDERS"> <id name="orderId" type="java.lang.Integer"> <column name="ORDER_ID" /> <generator class="assigned" /> </id> <property name="orderName" type="java.lang.String"> <column name="ORDER_NAME" /> </property> <many-to-one name="customer" class="com.dx.hibernate.onetomany.Customer"> <column name="CUSTOMER_ID" /> </many-to-one> </class> </hibernate-mapping>
初始化项目时,生成sql语句:
Hibernate: create table CUSTOMER ( CUSTOMER_ID integer not null auto_increment, CUSTOMER_NAME varchar(255), primary key (CUSTOMER_ID) ) engine=InnoDB Hibernate: create table ORDERS ( ORDER_ID integer not null auto_increment, ORDER_NAME varchar(255), CUSTOMER_ID integer, primary key (ORDER_ID) ) engine=InnoDB Hibernate: alter table ORDERS add constraint FKkdbly1ij6f4kqh378kfne6ilx foreign key (CUSTOMER_ID) references CUSTOMER (CUSTOMER_ID)
测试代码1:
package com.dx.hibernate.onetomany; import static org.junit.Assert.fail; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestMain { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build(); Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build(); sessionFactory = metadata.getSessionFactoryBuilder().build(); session = sessionFactory.getCurrentSession(); transaction = session.beginTransaction(); } @Test public void test() { Customer customer = new Customer("customer1"); Order order1 = new Order("order1", customer); Order order2 = new Order("order2", customer); session.save(customer); session.save(order1); session.save(order2); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } }
测试执行sql:
Hibernate: insert into CUSTOMER (CUSTOMER_NAME) values (?) Hibernate: insert into ORDERS (ORDER_NAME, CUSTOMER_ID) values (?, ?) Hibernate: insert into ORDERS (ORDER_NAME, CUSTOMER_ID) values (?, ?)
测试代码2:
@Test public void test() { Order order = (Order) session.get(Order.class, 1); System.out.println(order.getOrderName()); System.out.println(order.getCustomer().getCustomerName()); }
测试结果:
测试通过,且查询语句为:
Hibernate: select order0_.ORDER_ID as ORDER_ID1_1_0_, order0_.ORDER_NAME as ORDER_NA2_1_0_, order0_.CUSTOMER_ID as CUSTOMER3_1_0_ from ORDERS order0_ where order0_.ORDER_ID=? order1 Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ from CUSTOMER customer0_ where customer0_.CUSTOMER_ID=? customer1
测试代码3:
@Test public void test() { Order order = (Order) session.get(Order.class, 1); System.out.println(order.getOrderName()); //System.out.println(order.getCustomer().getCustomerName()); session.close(); System.out.println(order.getCustomer().getCustomerName()); }
测试结果不通过,执行sql语句:
Hibernate: select order0_.ORDER_ID as ORDER_ID1_1_0_, order0_.ORDER_NAME as ORDER_NA2_1_0_, order0_.CUSTOMER_ID as CUSTOMER3_1_0_ from ORDERS order0_ where order0_.ORDER_ID=? order1
测试4:
修改Order.hbm.xml
<many-to-one name="customer" class="com.dx.hibernate.onetomany.Customer" fetch="join"> <column name="CUSTOMER_ID" /> </many-to-one>
测试代码:
Order order = (Order) session.get(Order.class, 1);
System.out.println(order.getOrderName());
System.out.println(order.getCustomer().getCustomerName());
测试通过,打印的sql语句:
Hibernate: select order0_.ORDER_ID as ORDER_ID1_1_0_, order0_.ORDER_NAME as ORDER_NA2_1_0_, order0_.CUSTOMER_ID as CUSTOMER3_1_0_, customer1_.CUSTOMER_ID as CUSTOMER1_0_1_, customer1_.CUSTOMER_NAME as CUSTOMER2_0_1_ from ORDERS order0_ left outer join CUSTOMER customer1_ on order0_.CUSTOMER_ID=customer1_.CUSTOMER_ID where order0_.ORDER_ID=?
测试代码5:
修改Order.hbm.xml
<many-to-one name="customer" class="com.dx.hibernate.onetomany.Customer" fetch="join"> <column name="CUSTOMER_ID" /> </many-to-one>
测试代码:
Order order = (Order) session.get(Order.class, 1); System.out.println(order.getOrderName()); System.out.println(order.getCustomer().getCustomerName()); session.close(); System.out.println(order.getCustomer().getCustomerName());
测试不通过。
2)从Customer到Order的关联是一对多关联。
Order.java
1 package com.dx.hibernate.onetomany; 2 3 public class Order { 4 private Integer orderId; 5 private String orderName; 6 7 public Order() { 8 super(); 9 } 10 11 public Order(String orderName) { 12 super(); 13 this.orderName = orderName; 14 } 15 16 public Integer getOrderId() { 17 return orderId; 18 } 19 20 public void setOrderId(Integer orderId) { 21 this.orderId = orderId; 22 } 23 24 public String getOrderName() { 25 return orderName; 26 } 27 28 public void setOrderName(String orderName) { 29 this.orderName = orderName; 30 } 31 32 }
Order.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-5-25 22:09:21 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate.onetomany.Order" table="ORDERS"> 7 <id name="orderId" type="java.lang.Integer"> 8 <column name="ORDER_ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="orderName" type="java.lang.String"> 12 <column name="ORDER_NAME" /> 13 </property> 14 </class> 15 </hibernate-mapping>
Customer.java
1 package com.dx.hibernate.onetomany; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class Customer { 7 private Integer customerId; 8 private String customerName; 9 private List<Order> orders = new ArrayList<Order>(); 10 11 public Customer() { 12 } 13 14 public Customer(String customerName) { 15 super(); 16 this.customerName = customerName; 17 } 18 19 public Integer getCustomerId() { 20 return customerId; 21 } 22 23 public void setCustomerId(Integer customerId) { 24 this.customerId = customerId; 25 } 26 27 public String getCustomerName() { 28 return customerName; 29 } 30 31 public void setCustomerName(String customerName) { 32 this.customerName = customerName; 33 } 34 35 public List<Order> getOrders() { 36 return orders; 37 } 38 39 public void setOrders(List<Order> orders) { 40 this.orders = orders; 41 } 42 }
Customer.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-5-25 22:09:21 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate.onetomany.Customer" table="CUSTOMER"> 7 <id name="customerId" type="java.lang.Integer"> 8 <column name="CUSTOMER_ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="customerName" type="java.lang.String"> 12 <column name="CUSTOMER_NAME" /> 13 </property> 14 <list name="orders" inverse="false" table="ORDERS" lazy="true"> 15 <key> 16 <column name="CUSTOMER_ID" /> 17 </key> 18 <list-index></list-index> 19 <one-to-many class="com.dx.hibernate.onetomany.Order" /> 20 </list> 21 </class> 22 </hibernate-mapping>
TestMain.java
package com.dx.hibernate.onetomany; import static org.junit.Assert.fail; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.query.Query; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestMain { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build(); Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build(); sessionFactory = metadata.getSessionFactoryBuilder().build(); session = sessionFactory.getCurrentSession(); transaction = session.beginTransaction(); } @SuppressWarnings("deprecation") @Test public void test() { Order order1 = new Order("order1"); Order order2 = new Order("order2"); Customer customer = new Customer("customer1"); customer.getOrders().add(order1); customer.getOrders().add(order2); session.save(customer); session.save(order1); session.save(order2); Customer customerFetch = (Customer) session.get(Customer.class, 1); System.out.println(customerFetch.getCustomerName()); System.out.println(customerFetch.getOrders().size()); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } }
测试结果:通过,打印信息如下:
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@320e400] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. Hibernate: create table CUSTOMER ( CUSTOMER_ID integer not null auto_increment, CUSTOMER_NAME varchar(255), primary key (CUSTOMER_ID) ) engine=InnoDB Hibernate: create table ORDERS ( ORDER_ID integer not null auto_increment, ORDER_NAME varchar(255), CUSTOMER_ID integer, orders_ORDER integer, primary key (ORDER_ID) ) engine=InnoDB Hibernate: alter table ORDERS add constraint FKkdbly1ij6f4kqh378kfne6ilx foreign key (CUSTOMER_ID) references CUSTOMER (CUSTOMER_ID) Hibernate: insert into CUSTOMER (CUSTOMER_NAME) values (?) Hibernate: insert into ORDERS (ORDER_NAME) values (?) Hibernate: insert into ORDERS (ORDER_NAME) values (?) customer1 2 Hibernate: update ORDERS set CUSTOMER_ID=?, orders_ORDER=? where ORDER_ID=? Hibernate: update ORDERS set CUSTOMER_ID=?, orders_ORDER=? where ORDER_ID=?
- 双向关联
Order.java
1 package com.dx.hibernate.onetomany; 2 3 public class Order { 4 private Integer orderId; 5 private String orderName; 6 private Customer customer; 7 8 public Order() { 9 super(); 10 } 11 12 public Order(String orderName) { 13 super(); 14 this.orderName = orderName; 15 } 16 17 public Integer getOrderId() { 18 return orderId; 19 } 20 21 public void setOrderId(Integer orderId) { 22 this.orderId = orderId; 23 } 24 25 public String getOrderName() { 26 return orderName; 27 } 28 29 public void setOrderName(String orderName) { 30 this.orderName = orderName; 31 } 32 33 public Customer getCustomer() { 34 return customer; 35 } 36 37 public void setCustomer(Customer customer) { 38 this.customer = customer; 39 } 40 41 }
Order.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-5-25 22:09:21 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate.onetomany.Order" table="ORDERS"> 7 <id name="orderId" type="java.lang.Integer"> 8 <column name="ORDER_ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="orderName" type="java.lang.String"> 12 <column name="ORDER_NAME" /> 13 </property> 14 <many-to-one name="customer" class="com.dx.hibernate.onetomany.Customer" lazy="proxy"> 15 <column name="CUSTOMER_ID"></column> 16 </many-to-one> 17 </class> 18 </hibernate-mapping>
Customer.java
1 package com.dx.hibernate.onetomany; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class Customer { 7 private Integer customerId; 8 private String customerName; 9 private List<Order> orders = new ArrayList<Order>(); 10 11 public Customer() { 12 } 13 14 public Customer(String customerName) { 15 super(); 16 this.customerName = customerName; 17 } 18 19 public Integer getCustomerId() { 20 return customerId; 21 } 22 23 public void setCustomerId(Integer customerId) { 24 this.customerId = customerId; 25 } 26 27 public String getCustomerName() { 28 return customerName; 29 } 30 31 public void setCustomerName(String customerName) { 32 this.customerName = customerName; 33 } 34 35 public List<Order> getOrders() { 36 return orders; 37 } 38 39 public void setOrders(List<Order> orders) { 40 this.orders = orders; 41 } 42 }
Customer.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-5-25 22:09:21 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate.onetomany.Customer" table="CUSTOMER"> 7 <id name="customerId" type="java.lang.Integer"> 8 <column name="CUSTOMER_ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="customerName" type="java.lang.String"> 12 <column name="CUSTOMER_NAME" /> 13 </property> 14 <list name="orders" inverse="false" table="ORDERS" lazy="true"> 15 <key> 16 <column name="CUSTOMER_ID" /> 17 </key> 18 <list-index></list-index> 19 <one-to-many class="com.dx.hibernate.onetomany.Order" /> 20 </list> 21 </class> 22 </hibernate-mapping>
测试1
1 package com.dx.hibernate.onetomany; 2 3 import static org.junit.Assert.fail; 4 5 import java.util.List; 6 7 import org.hibernate.Session; 8 import org.hibernate.SessionFactory; 9 import org.hibernate.Transaction; 10 import org.hibernate.boot.Metadata; 11 import org.hibernate.boot.MetadataSources; 12 import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl; 13 import org.hibernate.boot.registry.StandardServiceRegistry; 14 import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 15 import org.hibernate.query.Query; 16 import org.junit.After; 17 import org.junit.Before; 18 import org.junit.Test; 19 20 public class TestMain { 21 private SessionFactory sessionFactory = null; 22 private Session session = null; 23 private Transaction transaction = null; 24 25 @Before 26 public void init() { 27 StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build(); 28 Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build(); 29 30 sessionFactory = metadata.getSessionFactoryBuilder().build(); 31 session = sessionFactory.getCurrentSession(); 32 transaction = session.beginTransaction(); 33 } 34 35 @SuppressWarnings("deprecation") 36 @Test 37 public void test() { 38 Order order1 = new Order("order1"); 39 Order order2 = new Order("order2"); 40 Customer customer = new Customer("customer1"); 41 customer.getOrders().add(order1); 42 customer.getOrders().add(order2); 43 44 session.save(customer); 45 session.save(order1); 46 session.save(order2); 47 48 Customer customerFetch = (Customer) session.get(Customer.class, 1); 49 50 System.out.println(customerFetch.getCustomerName()); 51 System.out.println(customerFetch.getOrders().size()); 52 53 } 54 55 @After 56 public void destory() { 57 transaction.commit(); 58 session.close(); 59 sessionFactory.close(); 60 } 61 }
测试打印信息:
Hibernate: create table CUSTOMER ( CUSTOMER_ID integer not null auto_increment, CUSTOMER_NAME varchar(255), primary key (CUSTOMER_ID) ) engine=InnoDB Hibernate: create table ORDERS ( ORDER_ID integer not null auto_increment, ORDER_NAME varchar(255), CUSTOMER_ID integer, orders_ORDER integer, primary key (ORDER_ID) ) engine=InnoDB Hibernate: alter table ORDERS add constraint FKkdbly1ij6f4kqh378kfne6ilx foreign key (CUSTOMER_ID) references CUSTOMER (CUSTOMER_ID) Hibernate: insert into CUSTOMER (CUSTOMER_NAME) values (?) Hibernate: insert into ORDERS (ORDER_NAME, CUSTOMER_ID) values (?, ?) Hibernate: insert into ORDERS (ORDER_NAME, CUSTOMER_ID) values (?, ?) customer1 2 Hibernate: update ORDERS set CUSTOMER_ID=?, orders_ORDER=? where ORDER_ID=? Hibernate: update ORDERS set CUSTOMER_ID=?, orders_ORDER=? where ORDER_ID=?
测试2:
@Test public void testUpdate(){ Customer customerFetch = (Customer) session.get(Customer.class, 1); customerFetch.getOrders().listIterator().next().setOrderName("ABC"); }
测试输出:
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ from CUSTOMER customer0_ where customer0_.CUSTOMER_ID=? Hibernate: select orders0_.CUSTOMER_ID as CUSTOMER3_1_0_, orders0_.ORDER_ID as ORDER_ID1_1_0_, orders0_.orders_ORDER as orders_O4_0_, orders0_.ORDER_ID as ORDER_ID1_1_1_, orders0_.ORDER_NAME as ORDER_NA2_1_1_, orders0_.CUSTOMER_ID as CUSTOMER3_1_1_ from ORDERS orders0_ where orders0_.CUSTOMER_ID=? Hibernate: update ORDERS set ORDER_NAME=?, CUSTOMER_ID=? where ORDER_ID=?
测试3:
@Test public void testRemove() { Customer customerFetch = (Customer) session.get(Customer.class, 2); Order order = customerFetch.getOrders().listIterator().next(); session.remove(order); }
测试输出:
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ from CUSTOMER customer0_ where customer0_.CUSTOMER_ID=? Hibernate: select orders0_.CUSTOMER_ID as CUSTOMER3_1_0_, orders0_.ORDER_ID as ORDER_ID1_1_0_, orders0_.orders_ORDER as orders_O4_0_, orders0_.ORDER_ID as ORDER_ID1_1_1_, orders0_.ORDER_NAME as ORDER_NA2_1_1_, orders0_.CUSTOMER_ID as CUSTOMER3_1_1_ from ORDERS orders0_ where orders0_.CUSTOMER_ID=? Hibernate: delete from ORDERS where ORDER_ID=?