映射一对多关联关系
在领域模型中,类与类之间最普遍的关系就是关联关系。
在UML中,关联是有方向的。
以Cuntomer和Order为例:一个用户能发出多个订单,而一个订单只能属于一个客户,从Order到Customer的关联是多对一关联,而从Customer到Order是一对多关联
单向关联:
如果Order中有一个Customer的一个引用的话,是单向多对一。
(order是多 ,customer是一)
如果Customer中有一个Order集合的引用的话,是单向一对多。
双向关联:
如果Customer中有一个对Order集合的引用,而Order中有一个对Customer的引用的话,属于双向关联
单向n-1
单向n-1关联只需从n的一端可以访问1的一端
域模型:从Order到Customer的多对一单向关联需要在Order类中定义一个Customer属性,而在Customer类中无需定义存放Order对象的集合属性
关系数据模型:ORDER表中的customer_id参照customer表的主键。
举例:
public class Customer {
private Integer customerId;
private String customerName;
public class Order {
private Integer orderId;
private String orderName;
private Customer customer = new Customer();
<hibernate-mapping >
<class name="com.clou.entity.n21.Customer" table="customers">
<id name="customerId" type="integer">
<column name="customer_id"></column>
<generator class="native"></generator>
</id>
<property name="customerName" type="string">
<column name="customer_name"></column>
</property>
</class>
</hibernate-mapping>
<hibernate-mapping package="com.clou.entity.n21">
<class name="Order" table="orders">
<id name="orderId" type="integer">
<column name="order_id"></column>
<generator class="native"></generator>
</id>
<property name="orderName" type="string">
<column name="order_name"></column>
</property>
<!--
映射多对一的关联关系 不能用property来描述
因为这已经不再是一个简单的属性
也不能用component 因为这也已经不再是一个简单的组成关系
(组件:组成关系中,在实体类中的引用分成两种,一种是值类型,一种是实体类型
值类型没有ID )
-->
<!-- 这个customer属性在Order表中对应一列 这列是customer_id(多表中的外键列) -->
<!-- 映射多对一的关联关系,使用many-to-one 来映射多对一的关联关系
name: 多这一段关联的一那一端的属性的名字
class: 一那一端的属性赌赢的类名
column : 一那一端在多的一端对应的数据表中的外键的列名
-->
<many-to-one name="customer" class="Customer" column="customer_id">
</many-to-one>
</class>
</hibernate-mapping>
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HibernateTest01 {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init(){
Configuration conf = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
sessionFactory = conf.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void destroy(){
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void testMany2One(){
Customer customer = new Customer();
customer.setCustomerName("BB");
Order order1 = new Order();
order1.setOrderName("order-3");
Order order2 = new Order();
order2.setOrderName("order-4");
//设定关联关系
order1.setCustomer(customer);
order2.setCustomer(customer);
//执行save操作:先插入Customer,再插入Order , 3条INSERT语句
//先插入1的一端, 再插入n 的一端 ,只有INSERT语句
// session.save(customer);
// session.save(order1);
// session.save(order2);
//先插入Order , 再插入Customer,3条INSERT ,两条UPDATE
//先插入n 的一端,再插入1的一端,会多出UPDATE语句
//因为在插入过的一端时,无法确定1的一端的外键值,所以只能等1的一端插入后,在额外发送UPDATE语句
//推荐线插入1的一端,后插入n的一端
session.save(order1);
session.save(order2);
session.save(customer);
}
@Test
public void testMany2OneGet(){
//1.若查询多的语段的一个对象,则默认情况下,只查询了多的一端的对象,
//而没有查询关联的1的那端的对象!
Order order = (Order) session.get(Order.class, 1);
System.out.println(order.getOrderName());//如果只有这一句,则控制台打印一句查询语句
System.out.println(order.getCustomer().getClass().getName());
session.close();
//在需要使用到关联的对象时,才发送对应的SQL语句。
Customer customer = order.getCustomer();
System.out.println(customer.getCustomerName());
//3.在查询Customer对象时 ,由多的一端,导航到一的一端时 ,
//若此时 session 已被关闭, 则默认情况下
//会发生LazyInitializationException 异常
//4.获取Order对象时 ,默认情况下,其关联的Customer对象时一个代理对象
//我们用的load()方法获取的数据库对象其实也是一个代理对象
//在我们用这个代理对象属性的时候,才会把代理对象进行初始化,如果我们在
//用这个代理对象之前把session给关了,会发生晚加载异常
}
public void testDelete(){
//在不设定级联关系的情况下,且1这一段的对象有n 的对象在引用,
//不能直接删除 1这一端的对象
Customer customer = (Customer) session.get(Customer.class, 1);
session.delete(customer);
}
/**
* 测试更新
*/
@Test
public void testUpdate(){
Order order = (Order) session.get(Order.class, 1);
order.getCustomer().setCustomerName("AAA");
}
}