Spring JPA Ⅹ 联表查询 之 ManyToMany

源码

@ManyToMany 注解实现多对多关系映射。我们还是以上面用户和房子为例(博主是多想要一套房子啊),毕竟一个用户可以拥有多套房子,而一套房子也可以写多个人的名字。
老规矩,实例之前先看看源码:

public @interface ManyToMany {

    Class targetEntity() default void.class;

    CascadeType[] cascade() default {};

    FetchType fetch() default LAZY;

    String mappedBy() default "";
}
复制代码

注解详情请见 注解属性详解 。其中需要注意的是  @ManyToMany 没有 orphanRemoval 的属性。多对多的情况下不能级联删除也能理解,毕竟不是一个人能说了算的。

单向联表

实例

user 实体

@Entity
@Data

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name;

    private int age;

    @ManyToMany
    private List<House> house;

}
复制代码

house 实体

@Entity
@Data
public class House {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String addr;

}
复制代码

小贴士

实例运行之后,会在数据库中生成一个中间表(user_house),这个表就是用来维护用户和房子映射关系的。

执行请求/user/findById?id=1,控制台打印如下:

Hibernate: 
    select
        house0_.user_id as user_id1_3_0_,
        house0_.house_id as house_id2_3_0_,
        house1_.id as id1_1_1_,
        house1_.addr as addr2_1_1_ 
    from
        user_house house0_ 
    inner join
        house house1_ 
            on house0_.house_id=house1_.id 
    where
        house0_.user_id=?
复制代码

查询结果

Optional[User(id=1, name=lili, age=11, house=[House(id=1, addr=江苏南京), House(id=2, addr=江苏无锡), House(id=3, addr=江苏苏州)])]

双向联表

实例

user 实体

@Entity
@Data
@JsonIgnoreProperties(value = {"hibernateLazyInitializer"})
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name;

    private int age;

    @ManyToMany
    @JsonIgnore
    public List<House> house;
}
复制代码

house 实体

@Entity
@Data
public class House {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String addr;

    @ManyToMany(mappedBy = "house")
    @JsonIgnore
    private List<User> user;
}
复制代码

小贴士

这里的 @JsonIgone 的注解就是为了解决堆栈溢出的问题。详情请见 Spring JPA 错题集

house 类中的 user 需要添加 mappedBy = "house",表示 house 是被动管理。如果不添加的话,系统会再生成一个中间表(house_user),这样一来,house 需要自己管理。在使用 house 获取 user 信息的时候会依赖中间表(house_user),导致 user 信息获取失败。

userControl 类

@GetMapping("findById")
public Optional<User> findById(int id){
    Optional<User> users = userService.findById(id);
    users.get().getHouse().forEach(v->{
        System.out.println(v.getId() + "-"+ v.getAddr());
    });
    return userService.findById(id);
}
复制代码

执行请求 /user/findById?id=33,控制台打印如下:

Hibernate: 
    select
        user0_.id as id1_2_0_,
        user0_.age as age2_2_0_,
        user0_.name as name3_2_0_ 
    from
        user user0_ 
    where
        user0_.id=?
[nio-7777-exec-7] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [33]
Hibernate: 
    select
        house0_.user_id as user_id1_3_0_,
        house0_.house_id as house_id2_3_0_,
        house1_.id as id1_1_1_,
        house1_.addr as addr2_1_1_ 
    from
        user_house house0_ 
    inner join
        house house1_ 
            on house0_.house_id=house1_.id 
    where
        house0_.user_id=?
[nio-7777-exec-7] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [33]
1-南京
2-苏州
3-无锡
复制代码

houseControl 类

@RequestMapping("findById")
public Optional<House> findById(int id){
    Optional<House> houses = houseService.findById(id);
    houses.get().getUser().forEach(v->{
        System.out.println(v.getName() + "-"+ v.getAge());
    });
    return houseService.findById(id);
}
复制代码

执行请求 /house/findById?id=1,控制台打印如下:

Hibernate: 
    select
        house0_.id as id1_1_0_,
        house0_.addr as addr2_1_0_ 
    from
        house house0_ 
    where
        house0_.id=?
[io-7777-exec-10] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
Hibernate: 
    select
        user0_.house_id as house_id2_3_0_,
        user0_.user_id as user_id1_3_0_,
        user1_.id as id1_2_1_,
        user1_.age as age2_2_1_,
        user1_.name as name3_2_1_ 
    from
        user_house user0_ 
    inner join
        user user1_ 
            on user0_.user_id=user1_.id 
    where
        user0_.house_id=?
[io-7777-exec-10] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
dada-22
tt-22
iii-221

作者:烟雨戏江南
链接:https://juejin.cn/post/7229220276847149114
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值