Spring DATA JPA中的关于多表连接的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring DATA JPA中的关于多表连接的问题相关的知识,希望对你有一定的参考价值。

请教一下大家,我现在有2个表,
第一个表是产品表Product,第二个表示规格表ProductSpec
product表中有一列是productSpecId,我希望得到的查询结果是product 表+ spec的描述
这个用spring data jpa通过注释应带怎么写?
如果要进行2个表的复杂查询呢?比如product的ID like 'A%' 且ProductSpec的描述(desc) like "刀具%"
T类怎么定义?还是每个表一个定义,还是将结果及定义T类

参考技术A 方法如下
public Page<Article> findByAuthor(String authorId,Pageable pageable)
Map<String,Object> searchParams=new HashMap<String, Object>();
Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
//添加查询条件
Specification<Article> spec = DynamicSpecifications.bySearchFilter(filters.values(), Article.class);
return articleDao.findAll(spec, pageable);

仅从 Spring Data JPA 中的联接表(多对多)中选择特定列

【中文标题】仅从 Spring Data JPA 中的联接表(多对多)中选择特定列【英文标题】:Select only specific columns from joined tables (Many-to-Many) in Spring Data JPA 【发布时间】:2021-05-04 04:28:49 【问题描述】:

目的是从连接表中选择列(多对多)。 我遇到的问题是从连接的多对多表中选择两列。

我正在使用 Springboot 2.3 和 Spring data Jpa。

我有这个数据模型,我想获取的是蓝框字段

所以本机查询可能看起来像这样(如果我是对的......)

SELECT bg.id, bg.name, p.name, c.name, c.short_desc FROM boardgame as bg 
 JOIN boardgame_category bgc on bg.id = bgc.fk_game 
 JOIN publisher p on bg.fk_publisher = p.id 
 JOIN category c on bgc.fk_category = c.id 
 WHERE bg.id = :id 

我首先尝试在 JPQL 语句中使用 dto

public class BoardgameDto 

    private long id;

    private String name;

    private String publisherName;

    private Set<CatregoryDto> categoryDto;

    // setter, getter etc...


public class CategoryDto 

    private String name;

    private String shortDesc;

    // setter, getter etc...


JQPL 查询可能看起来像这样,但它不起作用(IDE 在 CategoryDto 上显示错误)

/* THIS DOESN'T WORK */
SELECT new org.moto.tryingstuff.dto.BoardgameDto(bg.id, bg.name, p.name, 
new org.moto.tryingstuff.dto.CategoryDto(c.name, c.short_desc)) FROM Boardgame as bg, Publisher as p, Category as c

好吧,我认为我这样做的问题是dto的构造函数无法接收集合as written here,我认为参数中的另一个构造函数也没有。

然后我开始研究 Criteria Queries,尤其是多选、Tuple、Dto,但看起来我遇到了同样的问题,所以我没有深入研究。

最后我使用了一个 JpaRepository,它是这样的 findById() 方法

public interface BoardgameRepository extends JpaRepository<Boardgame, Long> 


// In a test or service method
Boardgame game = repository.findById(long id);

然后我通过服务或控制器层中的映射过滤我需要保留的字段。所以前台只收到需要的数据。

但感觉有点矫枉过正, 我是否遗漏了什么,框架中允许我只选择特定列的任何部分?

【问题讨论】:

【参考方案1】:

正如您所写,您不能将集合用作构造函数表达式的参数。这是因为表达式被应用于结果集中的每条记录。这些记录是一个扁平的数据结构。它们不包含任何集合。您的数据库会为该集合中的每个元素返回一条新记录。

但是您的constructor expression 因其他原因而失败。您正在尝试组合 2 个构造函数表达式,这不受支持。您需要删除第二个表达式并在 DTO 的构造函数中执行该操作。

因此,您的查询应如下所示:

SELECT new org.moto.tryingstuff.dto.BoardgameDto(bg.id, bg.name, p.name, c.name, c.short_desc) FROM Boardgame as bg <Your JOIN CLAUSES HERE>

你的 BoardgameD 的构造函数是这样的:

public class BoardgameDto 

  public BoardgameDto(Long id, String gameName, String publisherName, String categoryName, String description) 
     this.id = id;
     this.name = gameName;
     this.publisherName = publisherName;
     this.category = new Category(categoryName, description);
  

  ...

【讨论】:

以上是关于Spring DATA JPA中的关于多表连接的问题的主要内容,如果未能解决你的问题,请参考以下文章

spring Data jpa 一对多关联 动态查询怎么写

Spring Data JPA 多对多表查询

Spring Data Jpa 复杂查询总结 (多表关联 以及 自定义分页 )

spring-data-jpa的简单使用动态sql分页排序

Spring Data JPA 规范 - 连接中的不同+按列排序

关于Spring-Data-Jpa的一些理解