@ManyToOne与@OneToMany | Spring Data JPA 多表查询

环境

Spring Boot : 2.1.14
Java : 1.8.3
IDEA : 2018.3.3


本文默认已经使用Spring Boot + Spring Data JPA 搭建好数据库层,DAO类已经编写完毕。
首先介绍下面要用到的两个表:subarea 和 subarea_set 表,其中 subarea 与 subarea_set 的关系是一对多的关系。subarea_set 中存在 subarea 的外键 subarea_id。
subarea 表对应的Java实体类如下:

@Entity
public class Subarea {

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

  // 省略其他属性和getter,setter方法  
}

subarea_set 表对用的Java实体类如下:

@Entity
public class SubareaSet {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  private long subareaId;

  // 省略其他属性和getter,setter方法 
}

只使用@OneToMany

如果想要在查询 subarea 的时候得到相对应的 subarea_set 的值。如在查询 id = 1 的 subarea 的时候,想要同时得到 subarea_id = 1 subarea_set 的信息,就要使用@OneToMany注解。下面是只是用@OneToMany的情况:
Subarea 类修改如下:

@Entity
public class Subarea {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  // 新增
  @OneToMany
  @JoinColumn(name = "subareaId")
  private List<SubareaSet> subareaSetList;
  // 省略其他属性和getter,setter方法  
}

SubareaSet 类不变:

@Entity
public class SubareaSet {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  private long subareaId;

  // 省略其他属性和getter,setter方法 
}

这样写,再通过 DAO.findAll() 进行查询,就能同时得到 subarea 和 subarea_set 的信息了。

只使用@ManyToOne

如果在查询 subarea_set 的时候,想要知道 subarea_id 对应的 subarea 的信息(比如 subarea 的 name),那么就可以在 SubareaSet 类中运用 @ManyToOne 注解
Subarea 类不变:

@Entity
public class Subarea {

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

  // 省略其他属性和getter,setter方法  
}

SubareaSet 类修改如下:

@Entity
public class SubareaSet {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  //private long subareaId;   不要这个属性
  @ManyToOne
  private Subarea subarea;

  // 省略其他属性和getter,setter方法 
}

值得一提的,在查询时直接使用 DAO.findAll() 方法即可。在插入时,需要按照下面的写法:

SubareaSet subareaSet = new SubareaSet();
Subarea subarea = new Subarea();
subarea.setId(1);     
subareaSet.setSubarea(subarea);
// 其他属性设置

DAO.insert(subareaSet);

同时使用@OneToMany和@ManyToOne

大多数时候我们都是需要两边都配置的。但是两边同时配置显然有一个问题:比如,查询 subarea ,会显示 subareaSetList ,subareaSetList 中的每一项都是 subareaSet ,subareaSet 中又有 subarea ,subarea 中又有 subareaList…这样不就是无限嵌套了嘛。为了解决这个方法,网上有说:增加@JsonIgnore注解。但是这样配置显然是不行的,在查询的时候就是为了能够查询关联表的数据才配置@OneToMany或者@ManyToOne,如果查询不返回了,那配置这个显然就没有意义了。所以正确的做法是使用 @JsonIgnoreProperties 注解

Subarea 类修改如下:

@Entity
public class Subarea {

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

  @OneToMany
  @JsonIgnoreProperties(value = {"subarea"})
  @JoinColumn(name = "subarea_id")
  private List<SubareaSet> subareaSetList;
  // 省略其他属性和getter,setter方法  
}

SubareaSet 类修改如下:

@Entity
public class SubareaSet {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  
  @ManyToOne
  @JsonIgnoreProperties(value = {"subareaSetList"})
  private Subarea subarea;

  // 省略其他属性和getter,setter方法 
}

这样配置,在查询的时候,就不会嵌套了。
值得一提的是,这里所有的配置都是最基础的,如果需要考虑性能问题,还是要写懒加载的。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Data JPA中,多表关联插入可以通过如下方式实现: 1. 定义实体类之间的关联关系 在实体类中使用注解来定义表之间的关联关系,例如: ``` @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToMany(mappedBy = "user") private List<Order> orders; } @Entity @Table(name = "order") public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne @JoinColumn(name = "user_id") private User user; } ``` 2. 创建DTO对象 创建一个DTO对象,用于接收前端传递的参数,例如: ``` public class OrderDTO { private Long userId; private String orderName; // getter and setter } ``` 3. 在Repository中定义保存方法 在Repository中定义一个保存方法,用于保存Order对象,并关联User对象,例如: ``` @Repository public interface OrderRepository extends JpaRepository<Order, Long> { @Transactional @Modifying @Query(value = "INSERT INTO `order` (`order_name`, `user_id`) VALUES (:orderName, :userId)", nativeQuery = true) void saveOrder(@Param("orderName") String orderName, @Param("userId") Long userId); } ``` 4. 在Service中调用Repository方法 在Service中调用Repository中定义的方法,将前端传递的参数转换为实体对象,例如: ``` @Service public class OrderServiceImpl implements OrderService { @Autowired private OrderRepository orderRepository; @Autowired private UserRepository userRepository; @Override public void saveOrder(OrderDTO orderDTO) { User user = userRepository.getOne(orderDTO.getUserId()); orderRepository.saveOrder(orderDTO.getOrderName(), user.getId()); } } ``` 这样就可以实现多表关联插入了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值