JPA 五种 映射关系

版权声明:如果觉得好的话,不防点个赞,那点你们认为不对或是需要补充,可以留言啊!本人原创,未经允许不得转载!! https://blog.csdn.net/qq_28289405/article/details/82496410

一、JPA_映射单向多对一的关联关系

1、创建实体类

//订单
@Table(name="JPA_ORDER")
@Entity
public class Order {
	
	private Integer id;	
	private String orderName;	
	private Customer customer;

	@Id
	@GeneratedValue
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Column(name="ORDER_NAME")
	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	//映射多对一的关联关系
	//使用 @ManyToOne 来映射多对一的关联关系
	//使用 @JoinColumn 来映射外键  name:外键键名
	@JoinColumn(name="CUSTOMER_ID")
	@ManyToOne
	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
}

 测试类:

   //数据表生成
	@Test
	public void testManyToOne(){
		
	}

 保存数据  :

保存多对一时,建议先保存1的一端,然后保存 n 的一端,这样不会多出额外的 UPDATE 语句

    @Test
	public void testManyToOnePersist(){
		Customer customer = new Customer();
		customer.setAge(15);
		customer.setBirth(new Date());
		customer.setCreatTime(new Date());
		customer.setEmail("[email protected]");
		customer.setLastName("EE");
		
		Order order1 = new Order();
		order1.setOrderName("O-EE-1");
		
		Order order2 = new Order();
		order2.setOrderName("O-EE-2");
		
		//设置关联关系
		order1.setCustomer(customer);
		order2.setCustomer(customer);
		
		//执行保存操作
		entityManager.persist(customer);
		entityManager.persist(order1);
		entityManager.persist(order2);
		
	}

   

输出的SQL语句 : 是3 条insert 语句 

如果把执行保存操作中调换顺序

 @Test
	public void testManyToOnePersist(){
		Customer customer = new Customer();
		customer.setAge(15);
		customer.setBirth(new Date());
		customer.setCreatTime(new Date());
		customer.setEmail("[email protected]");
		customer.setLastName("GG");
		
		Order order1 = new Order();
		order1.setOrderName("g-GG-1");
		
		Order order2 = new Order();
		order2.setOrderName("g-GG-2");
		
		//设置关联关系
		order1.setCustomer(customer);
		order2.setCustomer(customer);

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

 那么执行结果: 【可以保存成功,SQL的变化】 三条insert 和两条update

这个时候外键是null 的 【下图 中 CUSTOMER_ID外键列的值 实际上为null 】

只有在保存外这个customer 之后,才知道外键列时谁,这个时候customer 才会有id; 【如下图】

然后jpa去维护关联关系,又额外有两个update。所以总结:

获取数据:

①、默认情况下,使用左外连接的方式来获取 n 的一端的对象和其关联的 1 的一端的对象

    @Test
	public void testManyToOneFind(){
		Order order = entityManager.find(Order.class, 1);
		System.out.println(order.getOrderName());
		
		System.out.println(order.getCustomer().getLastName());
	}

 执行的结果: 【一条select 语句】

②、可使用 @ManyToOne 中的 fetch 属性来修改默认的关联属性的加载策略   【懒加载】

 还是同样的测试 ,运行结果:  先生成Order 的信息 , 再打印Customer --查询customer 的语句 【两条SQL语句】

删除数据:

①、删除

    @Test
	public void testManyToOneRemove(){
		Order order = entityManager.find(Order.class, 1);
		entityManager.remove(order);
	}

运行结果: 一个select 一个 delete 

②、不能直接删除1 的一端,因为有外键关联

    @Test
	public void testManyToOneRemove(){
	
		Customer customer = entityManager.find(Customer.class, 7);
		entityManager.remove(customer);
		
	}

修改数据:

    @Test
	public void testManyToOneUpdate(){
		Order order = entityManager.find(Order.class, 2);
		order.getCustomer().setLastName("FFF");
		
	}

二、JPA_映射单向一对多的关联关系

生成数据表:

    @Test
	public void testOneToMany(){
		
	}

保存数据:

单向 1-n 关联关系执行保存时,一定会多出UPDATE语句,因为n 的一端在插入时不会同时插入外键列

    @Test
	public void testOneToManyPersist(){
		Customer customer = new Customer();
		customer.setAge(18);
		customer.setBirth(new Date());
		customer.setCreatTime(new Date());
		customer.setEmail("[email protected]");
		customer.setLastName("ZZ");
		
		Order order1 = new Order();
		order1.setOrderName("O-ZZ-1");
		
		Order order2 = new Order();
		order2.setOrderName("O-ZZ-2");
		
		//建立关联关系
		customer.getOrders().add(order1);
		customer.getOrders().add(order2);
		
		//执行保存操作
		
		entityManager.persist(customer);
		entityManager.persist(order1);
		entityManager.persist(order2);	
	}

 结果是在控制台输出3条 insert 语句 和两条 update语句

 

查询数据:

①、默认对关联的多的一方使用懒加载的加载策略

    @Test
	public void testOneToManyFind(){
		Customer customer = entityManager.find(Customer.class, 9);
		System.out.println(customer.getLastName());
		System.out.println(customer.getOrders().size());
	}

 

②、可以使用 @OneToMany 的fetch 属性来修改默认的加载策略

测试:

    @Test
	public void testOneToManyFind(){
		Customer customer = entityManager.find(Customer.class, 9);
		System.out.println(customer.getLastName());
		System.out.println(customer.getOrders().size());
	}

运行结果变成了主外连接

删除数据:

①、默认情况下,若删除 1 的一端,则想把关联 n 的一端的外键置空,然后进行删除

    @Test
	public void testOneToManyRemove(){
		Customer customer = entityManager.find(Customer.class, 9);
		entityManager.remove(customer);
	}

 运行结果  : 查询,然后把外键制空 , 最后删除

   

   

②、可以通过修改 @OneToMany 的 cascade 属性来修改默认的删除策略

    //默认情况下,若删除 1 的一端,则想把关联 n 的一端的外键置空,然后进行删除
	//可以通过修改 @OneToMany 的 cascade 属性来修改默认的删除策略
	@Test
	public void testOneToManyRemove(){
		Customer customer = entityManager.find(Customer.class, 8);
		entityManager.remove(customer);
	}
	

 

 更新数据:

    @Test
	public void testOneToManyUpdate(){
		Customer customer = entityManager.find(Customer.class, 11);	
		customer.getOrders().iterator().next().setOrderName("O-xxx-11");
	}

  

三、JPA_映射双向一对多的关联关系  和双向多对一是一样的

1、实体类:   Order  的实体类 加上  private Customer customer;,Customer 的实体类不变

@Table(name="JPA_ORDERS")  //订单
@Entity
public class Order {
	private Integer id;
	private String orderName;
	private Customer customer;

	@Id
	@GeneratedValue
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}

	@Column(name="ORDER_NAME")
	public String getOrderName() {
		return orderName;
	}
	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	@JoinColumn(name="CUSTOMER_ID")
	@ManyToOne(fetch=FetchType.LAZY)
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
}

 保存数据:

①、结论:若是双向1 - n 的关联关系,执行保存时:

若是先保存 n 的一端 , 再保存 1 的一端,默认情况下会多出 4 (n) 条 UPDATE 语句。

若是先保存 1 的一端,再保存 n 的一端,默认情况下会多出 2(n)  条 UPDATE 语句

    @Test
	public void testOneToManyDouble(){
		Customer customer = new Customer();
		customer.setAge(18);
		customer.setBirth(new Date());
		customer.setCreatTime(new Date());
		customer.setEmail("[email protected]");
		customer.setLastName("yy");
		
		Order order1 = new Order();
		order1.setOrderName("O-YY-1");
		
		Order order2 = new Order();
		order2.setOrderName("O-YY-2");
		
		//建立关联关系
		customer.getOrders().add(order1);
		customer.getOrders().add(order2);
		
		order1.setCustomer(customer);
		order2.setCustomer(customer);
		
		//执行保存操作
		entityManager.persist(order1);
		entityManager.persist(order2);	

        entityManager.persist(customer);
	}

会有四条update 语句输出 

 

②、控制台多出2条 UPDATE 语句 

在进行双向 1-n 关联关系时,建议使用 n 的一方来维护关联关系,而1 的一方不维护关联关系,这样会有效的减少SQL语句。

    @Test
	public void testOneToManyDouble2(){
		Customer customer = new Customer();
		customer.setAge(18);
		customer.setBirth(new Date());
		customer.setCreatTime(new Date());
		customer.setEmail("[email protected]");
		customer.setLastName("ss");
		
		Order order1 = new Order();
		order1.setOrderName("O-SS-1");
		
		Order order2 = new Order();
		order2.setOrderName("O-SS-2");
		
		//建立关联关系
		customer.getOrders().add(order1);
		customer.getOrders().add(order2);
		
		order1.setCustomer(customer);
		order2.setCustomer(customer);
		
		//执行保存操作  =====》 更改顺序
		entityManager.persist(order1);
		entityManager.persist(order2);	
		
		entityManager.persist(customer);
	}

 结果大家自己去实现之后的控制台看吧 ,数据已经成功的保存在数据库里了。

③、注意:若在 1 的一端的 @OneToMany  中使用  mappedBy 属性,则 @OneToMany 端就不能再使用 @JoinColumn 属性了。

四、JPA_映射双向一对一的关联关系

五、JPA_映射双向多对多的关联关系

猜你喜欢

转载自blog.csdn.net/qq_28289405/article/details/82496410