JPA中OneToMany

@ManyToMany

我们假设有咖啡,订单。咖啡和订单的关系就是多对多的关系。一个咖啡可以属于多个订单,一个订单也可以包含多种咖啡。

示例涉及的表:

咖啡类:

@Entity
@Table(name = "T_MENU")
@Builder
@Data
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class Coffee extends BaseEntity implements Serializable {
    private String name;
    private Money price;
}

订单类:

@Entity
@Table(name = "T_ORDER")
@Data
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CoffeeOrder extends BaseEntity implements Serializable {
    private String customer;
    @ManyToMany
    @JoinTable(name = "T_ORDER_COFFEE")
    @OrderBy("id")
    private List<Coffee> items;
    @Enumerated
    @Column(nullable = false)
    private OrderState state;
}

订单的items属性上标注@ManyToMany。@JoinTable可以指定生成的中间表表名。

如果不指定,会采用表名+变量名的命名方式生成中间表:t_order_items

注解产生的作用:

查看Hibernate建表的打印语句:

Hibernate: 
    
    create table t_coffee (
       id bigint not null auto_increment,
        create_time datetime,
        update_time datetime,
        age varchar(255),
        name varchar(255),
        price decimal(19,2),
        primary key (id)
    ) engine=MyISAM
Hibernate: 
    
    create table t_order (
       id bigint not null auto_increment,
        create_time datetime,
        update_time datetime,
        customer varchar(255),
        state integer not null,
        primary key (id)
    ) engine=MyISAM
Hibernate: 
    
    create table t_order_coffee (
       coffee_order_id bigint not null,
        items_id bigint not null
    ) engine=MyISAM
   
Hibernate: 
    
    alter table t_order_coffee 
       add constraint FKcm20cgbnblo27okpnlk0njdwy 
       foreign key (items_id) 
       references t_coffee (id)
Hibernate: 
    
    alter table t_order_coffee 
       add constraint FK33ucji9dx64fyog6g17blpx9v 
       foreign key (coffee_order_id) 
       references t_order (id)

可以看出,标注@ManyToMany后,会生成一个中间表t_order_coffee,

它会把咖啡表和订单表的id作为表的两个列。名称的生成规则是,注解所在表的外键 列根据当前类加上id 比如:coffee_order_id , 另一个则根据变量名+id:items_id

随后的alter语句,则将中间表的两个列分别和对应的表做外键关联。

也就是说,中间表每条记录保存了两个外键对应的值。并且订单是维护方。

完整的注解如下:

 @ManyToMany
 @JoinTable(name = "T_ORDER_COFFEE",joinColumns = @JoinColumn(name = "coffee_order_id",referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name="coffee_id",referencedColumnName = "id"))
    @OrderBy("id")
    private List<Coffee> items;

可以指定生成中间表 的表名,列名称以及关联的外键。@OrderBy这里是对取出的集合做一个排序。

另外只需要在咖啡和订单类两者的一个标注注解即可。

如何保存数据和查询数据:
  • 保存数据:
		//创建一个咖啡对象并保存
		Coffee latte = Coffee.builder().name("latte")
				.price(Money.of(CurrencyUnit.of("CNY"), 30.0))
				.build();
		coffeeRepository.save(latte);
		//创建第二个咖啡对象
		Coffee espresso = Coffee.builder().name("espresso")
				.price(Money.of(CurrencyUnit.of("CNY"), 20.0))
				.build();
		coffeeRepository.save(espresso);
		//创建一个订单,并将一个咖啡集合设置进去,最后保存后,中间表就会产生一条记录
		CoffeeOrder order = CoffeeOrder.builder()
				.customer("Li Lei")
				.items(Collections.singletonList(espresso))
				.state(OrderState.INIT)
				.build();
		orderRepository.save(order);
  • 查询记录:
//查询订单集合,则咋结果集中就会有对应的咖啡集合。
list = orderRepository.findByCustomerOrderById("Li Lei");
  • 删除:

如果此时执行删除订单操作:

orderRepository.deleteById(1L);

实际会执行两条删除语句:会同时删掉订单和中间表中和该订单关联的数据。

但是如果删除得是咖啡,则中间表的数据不会删除。

Hibernate: 
    delete 
    from
        t_order_coffee 
    where
        coffee_order_id=?
Hibernate: 
    delete 
    from
        t_order 
    where
        id=?

总结:

@ManyToMany注解的作用是帮助我们生成一张维护A和B两者关系的中间表。中间表维护了A,B两个表的主键。表名称和列名称会自动生成,也可以通过注解进行声明。多对多关系建立时,注解所在的表,是关系的维护方,所以当删除维护方时,会同时删除中间表的相关数据。查询操作,会查到关联的集合对象。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值