JPA-4 映射关联关系

  关联关系包括单向多对一、单向一对多、双向一对一、双向多对一和双向多对多共五种。
  映射关联关系的具体实现代码下载地址:http://download.csdn.net/download/bingbeichen/9807425


1. 映射单向多对一关联关系

  以Customer和Order为例,多个Order可以同属于一个用户。

@Table(name="JPA_ORDERS")
@Entity
public class Order {

    private Integer id;
    private String orderName;
    private Customer customer;

    /**
     * 映射单向多对一关联关系:
     *  1). 使用@ManyToOne注解来映射单向多对一关联关系
     *  2). 使用@JoinColumn注解来映射外键
     *  3). 可以使用@ManyToOne的fetch属性设定关联属性的加载策略
     * @return
     */
    @JoinColumn(name="CUSTOMER_ID")
    @ManyToOne(fetch=FetchType.LAZY)
    public Customer getCustomer() {
        return customer;
    }

    // ...

}
public class JPATestSingleManyToOne {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    /**
     * 单向多对一关联关系之保存:建议先保存1的一端再保存n的一端,以免额外多出UPDATE语句
     */
    @Test
    public void testManyToOnePersist() {
        // 1端
        Customer customer = new Customer(null, "qiaobb", "qiaobb@163.com", 23, new Date(), new Date());

        // n端
        Order order1 = new Order(null, "ORDER-JPA", customer);
        Order order2 = new Order(null, "ORDER-HIBERNATE", customer);

        // 保存1端
        entityManager.persist(customer);

        // 保存n端
        entityManager.persist(order1);
        entityManager.persist(order2);
    }

    /**
     * 单向多对一关联关系之查找:
     *  1). 默认情况下使用左外连接的方式来获取n的一端的对象及其关联的1的一端的对象
     *  2). 可以使用@ManyToOne的fetch属性设定关联属性的加载策略
     */
    @Test
    public void testMangToOneFind() {
        Order order = entityManager.find(Order.class, 1);
        System.out.println(order.getOrderName());

        System.out.println(order.getCustomer().getName());
    }

    /**
     * 单向多对一关联关系之删除:不能直接删除1的一端,因为有外键约束
     */
    @Test
    public void testManyToOneRemove() {
//      Order order = entityManager.find(Order.class, 1);
//      entityManager.remove(order);

        Customer customer = entityManager.find(Customer.class, 4);
        entityManager.remove(customer);
    }

    /**
     * 单向多对一关联关系之更新:
     */
    @Test
    public void testManyToOneUpdate() {
        Order order = entityManager.find(Order.class, 1);
        order.getCustomer().setName("sunaf");
    }

    @Before
    public void init() {
        String persistenceUnitName = "JPA-4-MappingRelation";
        entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
        entityManager = entityManagerFactory.createEntityManager();
        entityTransaction = entityManager.getTransaction();

        // 开启事务
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

}

2. 映射单向一对多关联关系

  以Customer和Order为例,一个Customer可以有多个Order。

@Table(name = "JPA_CUSTOMERS")
@Entity
public class Customer {

    private Integer id;
    private String name;
    private String email;
    private Integer age;
    private Date createTime;
    private Date birthday;
    private Set<Order> orders = new HashSet<>();

    /**
     * 映射单向一对多的关联关系:
     *  1). 使用@@OneToMany注解来映射单向一对多关联关系
     *  2). 使用@JoinColumn注解来映射外键列的名称
     *  3). 可以使用@OneToMany的fetch属性修改默认的加载策略
     *  4). 可以通过@OneToMany的cascade属性来修改默认的删除策略,如级联删除cascade={CascadeType.REMOVE}
     * @return
     */
    @JoinColumn(name="CUSTOMER_ID")
    @OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.REMOVE})
    public Set<Order> getOrders() {
        return orders;
    }

    // ... 

}
public class JPATestSingleOneToMany {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    /**
     * 单向一对多关联关系之保存:会额外多出UPDATE语句,因为由n的一端维护关联关系
     *  n的一端在插入时不会同时插入外键列
     */
    @Test
    public void testOneToManyPersist() {
        // 1端
        Customer customer = new Customer(null, "qiaobb", "qiaobb@163.com", 23, new Date(), new Date());

        // n端
        Order order1 = new Order(null, "ORDER-JPA");
        Order order2 = new Order(null, "ORDER-HIBERNATE");

        // 建立关联关系
        customer.getOrders().add(order1);
        customer.getOrders().add(order2);

        // 保存n端
        entityManager.persist(order1);
        entityManager.persist(order2);

        // 保存1端
        entityManager.persist(customer);
    }

    /**
     * 单向一对多关联关系之查找:
     *  1). 默认情况下对n的一端使用懒加载的加载策略
     *  2). 可以使用@OneToMany的fetch属性修改默认的加载策略
     */
    @Test
    public void testOneToManyFind() {
        Customer customer = entityManager.find(Customer.class, 1);
        System.out.println(customer);

        System.out.println(customer.getOrders());
    }

    /**
     * 单向一对多关联关系之删除:默认情况下,删除1的一端时,则先把n的一端的外键置空,再进行删除
     * 可以通过@OneToMany的cascade属性来修改默认的删除策略,如级联删除cascade={CascadeType.REMOVE}
     */
    @Test
    public void testOneToManyRemove() {
//      Order order = entityManager.find(Order.class, 1);
//      entityManager.remove(order);

        Customer customer = entityManager.find(Customer.class, 1);
        entityManager.remove(customer);
    }

    /**
     * 单向一对多关联关系之更新:
     */
    @Test
    public void testOneToManyUpdate() {
        Customer customer = entityManager.find(Customer.class, 2);
        customer.getOrders().iterator().next().setOrderName("BBBBB");
    }

    @Before
    public void init() {
        String persistenceUnitName = "JPA-4-SingleOneToMany";
        entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
        entityManager = entityManagerFactory.createEntityManager();
        entityTransaction = entityManager.getTransaction();

        // 开启事务
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

}

3. 映射双向多对一关联关系

  以Customer和Order为例,一个Customer可以有多个Order,多个Order也可以同属于一个Order。

// Customer类核心代码:
private Set<Order> orders = new HashSet<>();

// 若在1的一端@OneToMany中使用mappedBy="customer"属性,则1的一端不能再使用@JoinColumn标记
// 其中customer对应于n的一端的Customer属性名
//  @JoinColumn(name="CUSTOMER_ID")
@OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.REMOVE}, mappedBy="customer")
public Set<Order> getOrders() {
    return orders;
}
// Order类核心代码:
private Customer customer;

@JoinColumn(name="CUSTOMER_ID")
@ManyToOne(fetch=FetchType.LAZY)
public Customer getCustomer() {
    return customer;
}
// JPATestDoubleManyToOne类的核心测试代码:
/**
 * 映射双向多对一的关联关系:
 *  1). 先保存n的一端再保存1的一端,默认情况下双方均维护关联关系,额外多出2n条UPDATE语句
 *  2). 先保存1的一端再保存n的一端,默认情况下双方均维护关联关系,额外多出1n条UPDATE语句
 *  3). 建议n的一方来维护关联关系,而1的一方不维护关联关系,以减少额外多出的UPDATE语句
 *  4). 若在1的一端@OneToMany中使用mappedBy="customer"属性,则1的一端不能再使用@JoinColumn标记
 */
@Test
public void testDoubleManyToOnePersist() {
    Customer customer = new Customer(null, "CCC", "CCC@163.com", 33, new Date(), new Date());
    Order order1 = new Order(null, "ORDER-CCC1");
    Order order2 = new Order(null, "ORDER-CCC2");

    customer.getOrders().add(order1);
    customer.getOrders().add(order2);
    order1.setCustomer(customer);
    order2.setCustomer(customer);

    // 执行保存操作
    entityManager.persist(customer);
    entityManager.persist(order1);
    entityManager.persist(order2);
}

4. 映射双向一对一关联关系

  映射双向一对一关联关系在执行保存操作时,默认不采用懒加载策略;可以在维护关联关系的一方使用懒加载策略,但不建议在不维护关联关系的一方使用。
  这里写图片描述


5. 映射双向多对多关联关系

  映射双向多对多关联关系在执行保存操作时,默认采用懒加载策略,即无论先获取哪一方,其对中间表而言均是平等的,均采用懒加载的方式。
  这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值