【发布时间】:2017-07-23 21:44:26
【问题描述】:
我正在编写基本上是广告服务的 Spring Boot 应用程序。在数据库中(我使用 PostgreSQL 方言)我存储类别树。每个类别都包含对其直接父级的引用。每个广告都有自己的类别,为了解决问题,您可以仅将广告分配给叶类别。
下面的图像捕获了结构。
现在我需要从数据库中检索特定类别的广告。但是假设我要检索类别 E 的所有广告。这意味着我要检索类别 E 的子类别的广告,但不一定是直接子类别的广告。在这种情况下,我想检索类别 G、H、I 和 J 的广告,因为它们都是叶子并且都是类别 E 的子节点。
如何通过 Spring 存储库实现它?以下是此示例的简化实体类。
类别...
@Entity
@Table(name = "categories")
public class Category {
@Id
@Column(name = "cat_id")
private int id;
@Column(name = "cat_name", length = 50, nullable = false, unique = true)
private String name;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "cat_parent", referencedColumnName = "cat_id", nullable = false)
private Category parent;
...
}
...和广告。
@Entity
@Table(name = "advertisements")
public class Advertisement {
@Id
@Column(name = "adv_id")
private long id;
@Column(name = "adv_title", length = 100, nullable = false)
private String title;
@Column(name = "adv_description", length = 5000, nullable = false)
private String description;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "adv_category", referencedColumnName = "cat_id", nullable = false)
private Category category;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "adv_owner", referencedColumnName = "user_id", nullable = false)
private User owner;
...
}
【问题讨论】:
-
您可以使用 Postgres 公用表表达式 (CTE) 编写本机查询。请参阅official documentation。
-
@manish 我没用过,我去看看。我想这与那些递归查询有关吗?看起来不是特别容易。
-
有两种方法可以创建分层数据结构。当结构中的对象持有对其直接父对象的引用时,该结构称为
Adjacency list。另一种选择是将结构建模为Nested set。在嵌套集中查找叶节点很简单,并且需要非常简单的 SQL 查询。然而,嵌套集的构造是复杂的,并且只有在层次结构树大部分是静态的并且不需要经常更改时它们实际上才有用。请仔细阅读这两个模型,看看嵌套集是否可以解决您的问题。 -
@manish 好吧,一旦我创建了类别树,我可能就不会更改它了。这只是我的硕士论文的项目,它不需要完美。所以
Nested set听起来是可行的解决方案。尽管如此,Adjacency tree似乎更加优雅。我找到了一个本地 SQL 查询来从根检索所有叶子,但我没有修改它,所以它会返回任何子树的叶子节点。
标签: java spring postgresql spring-boot repository