Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何查询深度未定义的层次分类树实体_Java_Spring Boot_Tree - Fatal编程技术网

Java 如何查询深度未定义的层次分类树实体

Java 如何查询深度未定义的层次分类树实体,java,spring-boot,tree,Java,Spring Boot,Tree,我使用springboot为购物网站创建了一个层次结构或树结构。我的问题是,在查找特定产品及其父产品时,如何查询这种结构: id, category_name, parent_id '1', 'Electronics', NULL '2', 'Gaming', NULL '3', 'Home Audio', '1' '4', 'Console', '2' '5', 'Sony', '4' '6', 'Kar

我使用springboot为购物网站创建了一个层次结构或树结构。我的问题是,在查找特定产品及其父产品时,如何查询这种结构:

id,  category_name,   parent_id
'1', 'Electronics',      NULL
'2', 'Gaming',           NULL
'3', 'Home Audio',       '1'
'4', 'Console',          '2'
'5', 'Sony',             '4'
'6', 'Karaoke',          '3'
这就是我所做的,关于我需要在实体上做什么来实现这个结构的任何指针,以及我如何查询它,即

还需要注意的是,我正在使用postgres数据库

public class CategoryService {

@Autowired
private CategoryRepository categoryRepository;

public void addCategory(Category category) {
    categoryRepository.save(category);
}
}
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    public void addProduct(Product product) {
        productRepository.save(product);
    }
   }
  • 类别中的findAllProducts和
  • 查找链接到产品的所有类别 类别实体

    @Entity
    @Table(name = "categories")
    public class Category {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @Column(nullable = false)
        private String categoryName;
    
            @ManyToOne
            @JoinColumn(name = "parent_id")
            private Category parent;
    
            @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE, orphanRemoval = true)
            private List<Category> children = new ArrayList<Category>();
    
        // Getter and setter removed for readability    
    }
    
    @Entity
    @Table(name = "products")
    public class Product {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "id")
        private Long id;
    
        @Version
        @Column(name = "version")
        private Integer version;
    
        private String name;
    
        private int quantity;
    
        @ManyToMany(cascade = CascadeType.ALL)
        @JoinTable(name = "products_categories", joinColumns = {
                @JoinColumn(name = "product_id", referencedColumnName = "id") }, inverseJoinColumns = {
                        @JoinColumn(name = "category_id", referencedColumnName = "id") })
        private List<Category> categories;
    
      // getters and setter omitted for readability
    
    }
    
    产品服务

    public class CategoryService {
    
    @Autowired
    private CategoryRepository categoryRepository;
    
    public void addCategory(Category category) {
        categoryRepository.save(category);
    }
    }
    
    public class ProductService {
    
        @Autowired
        private ProductRepository productRepository;
    
        public void addProduct(Product product) {
            productRepository.save(product);
        }
       }
    

    可以使用递归查询选择给定类别的父级

    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.data.repository.query.Param;
    
    import java.util.List;
    
    public interface CategoryRepository extends JpaRepository<Category, Long> {
    
      @Query(
          value = "WITH RECURSIVE ancestors(id, parent_id, category_name, lvl) AS ("
              + "   SELECT cat.id, cat.parent_id, cat.category_name, 1 AS lvl "
              + "   FROM categories cat "
              + "   WHERE cat.id = :categoryId "
              + "   UNION ALL "
              + "   SELECT parent.id, parent.parent_id, parent.category_name, child.lvl + 1 AS lvl "
              + "   FROM categories parent "
              + "   JOIN ancestors child "
              + "   ON parent.id = child.parent_id "
              + " )"
              + "SELECT category_name from ancestors ORDER BY lvl DESC"
          , nativeQuery = true)
      List<String> findAncestry(@Param("categoryId") Long categoryId);
    }
    
    import org.springframework.data.jpa.repository.JpaRepository;
    导入org.springframework.data.jpa.repository.Query;
    导入org.springframework.data.repository.query.Param;
    导入java.util.List;
    公共接口类别repository扩展了JpaRepository{
    @质疑(
    value=“递归祖先(id、父项id、类别名称、lvl)为(”
    +“选择cat.id、cat.parent\u id、cat.category\u name、1作为lvl”
    +“来自类别cat”
    +“其中cat.id=:categoryId”
    +“全民联合”
    +选择parent.id、parent.parent\u id、parent.category\u name、child.lvl+1作为lvl
    +“来自父类别”
    +“加入祖先的孩子”
    +“ON parent.id=child.parent\u id”
    + " )"
    +“按lvl DESC从订单中选择类别名称”
    ,nativeQuery=true)
    列出findAncestry(@Param(“categoryId”)长categoryId);
    }
    
    以下是创建类别层次结构并对其进行查询的测试:

    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class HierarchyTest {
    
      @Autowired
      CategoryRepository categoryRepository;
    
      @Test
      public void testCategoryRepository() {
        String[] electronicsCategoryNames = {"Electronics", "Home Audio", "Karaoke"};
        String[] gamingCategoryNames = {"Gaming", "Console", "Sony"};
    
        Category karaoke = createCategories(electronicsCategoryNames);
        Category sony = createCategories(gamingCategoryNames);
    
        findAncestry(karaoke, electronicsCategoryNames);
        findAncestry(sony, gamingCategoryNames);
      }
    
      Category createCategories(String[] categoryNames) {
        Category parent = null;
    
        for (String categoryName : categoryNames) {
          Category category = new Category();
          category.setCategoryName(categoryName);
          category.setParent(parent);
          parent = categoryRepository.save(category);
        }
    
        Assert.assertNotNull("category.id", parent.getId());
        return parent;
      }
    
    
      void findAncestry(Category category, String[] categoryNames) {
        List<String> ancestry = categoryRepository.findAncestry(category.getId());
        Assert.assertEquals("ancestry.size", categoryNames.length, ancestry.size());
    
        for (int i = 0; i < categoryNames.length; i++) {
          Assert.assertEquals("ancestor " + i, categoryNames[i], ancestry.get(i));
        }
      }
    }
    
    import org.junit.Assert;
    导入org.junit.Test;
    导入org.junit.runner.RunWith;
    导入org.springframework.beans.factory.annotation.Autowired;
    导入org.springframework.boot.test.context.SpringBootTest;
    导入org.springframework.test.context.junit4.SpringRunner;
    导入java.util.List;
    @RunWith(SpringRunner.class)
    @春靴测试
    公共类层次结构测试{
    @自动连线
    分类报告分类报告;
    @试验
    public void testCategoryRepository(){
    字符串[]electronicsCategoryNames={“电子”、“家庭音频”、“卡拉OK”};
    字符串[]gamingCategoryNames={“Gaming”、“Console”、“Sony”};
    类别卡拉OK=创建类别(电子分类名称);
    类别索尼=创建类别(gamingCategoryNames);
    findAncestry(卡拉OK、电子姓名);
    findAncestry(索尼、gamingCategoryNames);
    }
    Category createCategories(字符串[]categoryNames){
    类别父项=null;
    for(字符串categoryName:categoryNames){
    类别=新类别();
    category.setCategoryName(categoryName);
    类别。setParent(父级);
    父项=categoryRepository.save(类别);
    }
    Assert.assertNotNull(“category.id”,parent.getId());
    返回父母;
    }
    void findAncestry(类别,字符串[]类别名称){
    List祖先=categoryRepository.findAncestry(category.getId());
    Assert.assertEquals(“祖先.size”,categoryNames.length,祖先.size());
    for(int i=0;i
    注意,这是在H2和PostgreSQL数据库上测试的。您可能需要根据正在使用的实际数据库修改本机查询

    PostgreSQL提供了关于如何工作的优秀文档,请参见:


    从SQL的角度,检查
    connectbypreor
    子句。我正在使用spring.jpa.hibernate.ddl-auto=create从这些实体创建数据库。答案似乎在问题中。关于你发布的代码,有什么具体的问题吗?当我使用它时,代码没有创建那个结构,所以当我尝试创建类别并将它们链接到产品时。好吧,你没有发布试图创建那个结构的代码,那么我们如何帮助呢?我如何修改查询以便在postgres中使用