使用JPA查询不同分页实体

huangapple go评论70阅读模式
英文:

Query different paginated entities using JPA

问题

我有一个名为"Folders"和"Files"的表。"Folders"和"Files"分别被映射到适当的实体"Folder"和"File"。

我需要进行分页请求,以分开的实体形式检索文件夹和文件。结果应该类似于json:

   {
      folders: [...],
      files: [...],
   }

此外,文件夹实体应始终在前。例如,如果总共有10个文件夹和10个文件,并且请求是
...?pageNumber=1&itemsPerPage=15
结果应为:

   {
      folders: [...], // 10个文件夹
      files: [...] // 5个文件
   }

"Folder"和"File"具有共同的字段,除了"Folder"有字段"parentFolderKey",而"File"实体则没有。此外,"File"实体有字段"folderKey",但"Folder"则没有。

如果只有一个实体,这就没问题了,但如何进行分页查询以构建具有不同字段(parentFolderKey、folderKey)的组合实体响应呢?我还在使用JPA存储库和Spring。你有什么建议?

英文:

I have table Folders and Files. Folders and Files are mapped to appropriate entities Folder and File.

I need to make a paginated request to retrieve folders and files as separate entities. As a result it should look like a json:

   {
      folders: [...],
      files: [...],
   }

Moreover folders entities should come always first. E.g. if we have total 10 folders and 10 files and request is
...?pageNumber=1&itemsPerPage=15
the result should be:

   {
      folders: [...], // 10 folders
      files: [...] // 5 files
   }

Folder and File have common fields except Folder have field 'parentFolderKey' and File entity don't. Also File entity have field 'folderKey', but Folder don't.

If it would be just one entity it will be ok but how to make a paginated query to build such response with combined entities which have different fields (parentFolderKey, folderKey)? I'm also using JPA repositories and Spring. What can you suggest?

答案1

得分: 1

好的,以下是翻译好的内容:

显而易见的答案是通过建立继承层次结构,将 FolderFile 关联起来,使它们成为“一个实体”。也许两者都可以继承自诸如 FileSystemEntry 的某个东西?

然后,您可以查询 FileSystemEntry 并按照鉴别器列进行 ORDER BY,以便将 Folder 放在顶部。将列表分割为 filesfolders 只是找到结果中第一个 File 的问题。

英文:

Well, the obvious answer would be to make them 'one entity' by tying Folder and File with an inheritance hierarchy. Perhaps both could inherit from something like a FileSystemEntry?

You could then query FileSystemEntry and ORDER BY the discriminator column to get Folders on top. Splitting the list into files and folders is simply a matter of finding the first File in the result.

答案2

得分: 1

如果我能够自己定义表结构,我会采用继承方法。由于FileFolder共享许多属性,这是最明显的方式。

但如果已经有了表结构,我会在Hibernate中使用@SubselectUNION结合的方法:

@Entity
@Subselect("SELECT concat('folder.', id) fid, parentFolderKey parentFolder_Id, ... FROM Folder"
         + " UNION SELECT concat('file.', id) fid, folderKey parentFolder_Id, ... FROM File")
@Synchronize({ "Folder", "File" })
public FolderOrFile {
  
  @Id
  private String fid;

  @ManyToOne
  private Folder parentFolder;

  ... 文件和文件夹的共同属性

  public boolean isFile() { return fid.startsWith("file."); }

}

@Synchronize注解用于确保在更改FolderFile实体时清除FolderOrFile的缓存。)

现在,您甚至可以为该实体创建带有分页的查询。

英文:

If I would be able to define the table structure myself, I would go with the inheritance approach. As File and Folder share many properties, this is the most obvious way.

But if there is already a table structure, I would use a @Subselect in Hibernate in combination with a UNION:

@Entity
@Subselect("SELECT concat('folder.', id) fid, parentFolderKey parentFolder_Id, ... FROM Folder"
         + " UNION SELECT concat('file.', id) fid, folderKey parentFolder_Id, ... FROM File")
@Synchronize({ "Folder", "File" })
public FolderOrFile {
  
  @Id
  private String fid;

  @ManyToOne
  private Folder parentFolder;

  ... Common properties of files and folders

  public boolean isFile() { return fid.startsWith("file."); }

}

(The @Synchronize annotation is for ensuring that the cache for FolderOrFile is cleared, when a Folder or File entity is changed.)

You can now create a query for that entity even with paging.

huangapple
  • 本文由 发表于 2020年9月1日 19:40:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/63686944.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定