当前位置: 首页 > 知识库问答 >
问题:

CrudRepository中的Spring findAll()方法不返回派生实体

方权
2023-03-14

因此,我有以下应用程序,它有一个名为Product的实体,它继承了另外两个实体(Product

public abstract class ProductController<T extends Product> {
    @Autowired
    private ProductService<T> productService;
    @PostMapping
    public ResponseEntity post(@RequestBody T product) {
        return ResponseEntity.ok(productService.save(product));
    }
    @GetMapping
    public ResponseEntity get() {
        return ResponseEntity.ok(productService.findAll());
    }
}

@RestController
@RequestMapping("/products/categories/bikes")
public class BikeController extends ProductController<Bike> {}

@RestController
@RequestMapping("/products/categories/wheels")
public class WheelController extends ProductController<Wheel> {}

实体:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    public Product() {}
    //getters and setters
}

@Entity
public class Bike extends Product {
    private String color;
    public Bike() {}
    //getters and setters
}
@Entity
public class Wheel extends Product {
    private Double diameter;
    public Wheel() {}
    //getters and setters
}

产品存储库:

public interface ProductRepository<T extends Product> extends CrudRepository<T, Long> {}

产品服务:

@Service
public class ProductService<T extends Product> {
    @Autowired
    private ProductRepository<T> productRepository;
    public T save(T product) {
        return productRepository.save(product);
    }
    public Iterable<T> findAll() { return productRepository.findAll(); }
}

运行程序后,它为每个实体创建三个表。如果我从具体控制器调用post方法,它会将实体添加到其表中。但是findAll()方法不是从具体表而是从产品表返回实体。所以我的问题是为什么会发生这种情况(即使我在存储库中指定了Entity类型)?

共有1个答案

督弘化
2023-03-14

您想要实现的是不可能的,因为BikejavaProducts的子类型,但不适用于JPA。在数据库中,它通常会为每个子类型拆分为不同的表,并且只能查询表(JPA将其视为实体)。所以Spring存储库也无法查询它,因为它在内部使用JPA。

请查看此处并阅读有关jpa继承的更多信息:https://www.baeldung.com/hibernate-inheritance

一般来说:每种产品都有不同的表格是不好的做法。每次添加新产品时,都必须在数据库中添加一个全新的类和表。最好的做法是为产品提供一个单独的实体/类(从而有一个表)和一个字段来区分不同类型的产品。最简单的形式是字符串productType,但我建议使用一个单独的实体productType,带有id和名称(最简单的形式),并且在Product和productType之间有一个关系。可以使用类型为Map的字段和ElementCollection(动态)附加数据存储附加数据,如颜色和直径(如此处所示:https://stackoverflow.com/a/15061468/7142748).

 类似资料:
  • 问题内容: 如下代码: 产生以下错误: 错误CS0738:“ InheritanceTest.MyData”未实现接口成员“ InheritanceTest.ISomeData.Data”。’InheritanceTest.MyData.Data’无法实现’InheritanceTest.ISomeData.Data’,因为它没有匹配的返回类型’System.Collections.Generic

  • 我可以写: 但这当然不起作用,因为调用返回的是而不是我想要的。 我可以通过在(以及和等)中键入类型并抑制警告来避免这个问题,但是即使只有(比方说)10个扩展的实体类,这仍然是为了键入而编写的样板代码。此外,我认为,如果我必须为每个派生类编写代码(无论多么小)(也会有其他类似的方法),那么拥有类层次结构的好处就会丧失很多。 对此有更好的解决方案吗? 更新:使用Java7。

  • 如果基类A有一个“public synchronized void method(){}”没有被它的派生类B重写,那么用来访问类B中的synchronized方法的锁是什么(即是派生类对象还是基类对象)?

  • 我为此使用了一个服务类,但为了最小的可重复示例而删除了它。目前findAll()正在返回一个空数组,而它应该从h2返回一个带有员工实体json的数组。我仍然不清楚Spring如何将数据处理到h2数据库中,所以我想这可能是我的问题的根源。 控制器: 存储库: 实体: 数据sql: schema.sql:

  • 我已经用openAPI生成器maven插件生成了rest api,并且我已经从接口重写了默认方法,但是上的POST请求提供了501,没有实现,就好像我没有在MyApiDelegateImpl中给出该方法的我自己的实现一样。 Maven插件配置: 我的实现: 如何让我的程序在具体类中使用我自己的方法实现,而不是接口中提供的默认实现?

  • 我读到了Crudrepository,这是一个接口,用于在特定类型的存储库上进行通用CRUD操作。 但是我们可以创建我们的自定义接口并扩展CrudRepository。