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

无法使MappedSuperClass抽象实体与Spring Boot和JPA一起工作

阎宾实
2023-03-14

我做了一些研究,我已经读了这本指南。

@MappedSuperClass
public abstract class Item{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(nullable = false)
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "item_id")
    private Set<Picture> pictures = new HashSet<>();

}
@Entity
public class Coke extends Item{

    @Column
    private String cokeProperty;

    @Column
    private String cokeProperty2;
}
@Entity
public class Sprite extends Item{

    @Column
    private String spriteProperty;

    @Column
    private String spriteProperty2;
}
@Entity
public class Picture {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;
}

在Application.Properties中配置了h2数据库的项的我的存储库

@Repository
public interface ItemRepository<Item, Long>{
}

实现itemservice接口并接受itemrepositorybean的服务:

@Service
public class ItemServiceImpl implements ItemService{

private ItemRepository repository;

public ItemServiceImpl(ItemRepository repository) {
    this.repository = repository;
}

@Override
public ResponseEntity<List<Item>> getAll(){
    return new ResponseEntity<>(repository.findAll(), HttpStatus.OK);
}

@Override
public ResponseEntity<Item> getById(Long id){
    Optional<Item> item = repository.findById(id);
    return new ResponseEntity<>(item.orElse(null), HttpStatus.OK);
}

@Override
public ResponseEntity<Item> create(Item item){
    return new ResponseEntity<>(repository.save(item), HttpStatus.CREATED);
}    }

然后是接受itemservicebean的控制器:

@RestController
@RequestMapping("/api/items")
public class ItemController{

    private ItemService service;

    public ItemController(ItemService service) {
        this.service = service;
    }

    @GetMapping("")
    public ResponseEntity<List<Item>> findAll(){
        return service.getAll();
    }

    @GetMapping("/{id}")
    public ResponseEntity<Item> findById(@PathVariable(name = "id") Long id){
        return service.getById(id);
    }

    @PostMapping("")
    public ResponseEntity<Item> save(@RequestBody Item item){
        return service.create(item);
    }
}
{
    "name": "Toyota Civic 3 days sale!!",
    "pictures": [
      {
        "name": "picture 1"
      },
      {
        "name": "picture 2"
      }
    ],
    "cokeProperty": "sweet",
    "cokeProperty2": "not healthy"
}

我还在我的抽象类上尝试了另一种策略:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

还是没有雪茄。同样的错误。有没有人能给我一点启示,对于被其他实体扩展的抽象实体,使用Spring Boot和JPA的正确方法?

共有1个答案

卫彭亮
2023-03-14

javax.persistence的@MappedSuperClass与这个问题没有直接关系。正如错误消息所指出的,原因在于Jackson-DataBind。

由于item是一个抽象类,所以Jackson无法确定它应该实例化哪个具体类,以便从JSON反序列化实体。这就是为什么item必须用对实现的引用来注释:

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.PROPERTY, property = "type"
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Coke.class, name = "coke"),
    @JsonSubTypes.Type(value = Sprite.class, name = "sprite")
})
public abstract class Item {

   // no changes

}

在JSON中也需要一个小的更改,因为它应该指向实现类型:

{
  "name": /* no changes  */,
  "type": "coke", /* new property */
  "pictures": /* no changes  */
}

允许的一个简短测试显示item现在已正确反序列化:

String json = "{\n" +
    "    \"name\": \"Toyota Civic 3 days sale!!\",\n" +
    "    \"type\": \"coke\"," +
    "    \"pictures\": [\n" +
    "      {\n" +
    "        \"name\": \"picture 1\"\n" +
    "      },\n" +
    "      {\n" +
    "        \"name\": \"picture 2\"\n" +
    "      }\n" +
    "    ],\n" +
    "    \"cokeProperty\": \"sweet\",\n" +
    "    \"cokeProperty2\": \"not healthy\"\n" +
    "}";

ObjectMapper mapper = new ObjectMapper();

Item item = mapper.readValue(json, Item.class);

System.out.println(item);

// outputs:
// Coke(super=Item(id=0, name=Toyota Civic 3 days sale!!, pictures=[Picture(id=0, name=picture 2), Picture(id=0, name=picture 1)]), cokeProperty=sweet, cokeProperty2=not healthy)

但这种改变不足以使您的服务工作。正如@Rujal Shrestha在他的评论中已经提到的,存储库定义和缺失的自动操作也存在问题。

 类似资料:
  • 我有一个用注释的抽象实体: 然后我从中继承实体,在每个实体中定义它们的id: 现在我想创建一个通用的JpaRepository,它接受从我的Base Entity扩展的任何类: 但Spring出现了一个异常,称BaseEntity没有ID: 请检查Plog在回答中的评论。我可以在服务的构造函数中注入每种存储库类型来解决这个问题

  • 问题内容: 我创建了一个空的抽象类,并从中继承了该类: 我期望输出是 但是,我得到的是 如果我删除(这样就变成一个普通的类)和/或如果我设置了其他值,问题(显然)就消失了。 这里发生了什么? 问题答案: 这实际上不是ABC的问题,而是PyMongo的问题。有一个关于它的问题在这里。似乎pymongo重写以返回某种数据库类。这意味着将返回一个数据库对象,该对象在布尔上下文中为true。这使ABCMe

  • 我使用下面的JPQL结构和SOUNDEX表达式来执行语音拼写匹配。 但是在createQuery过程中,它给了我以下错误…如果我在这里做错了什么事,请让我知道。如果我用鞋面代替音响,它工作得很好。另外,我在数据库上运行了查询,结果是正常获取的。 SystemErr R optimum.clinicals.waf.GeneralFailureException:org.apache.openjpa.

  • 以下结构(在中)不允许我在模块中导入类: 顶层的为空。以下是剩余的文件: a b: 在Windows上,如果我尝试运行(从文件夹中)而不做任何其他操作,我会得到以下错误: 如果我在顶层添加一个: 包含 并运行(从内),我得到同样的错误。 如果我将更改为 然后运行(从文件夹中)或(从)中,我得到了 python文档让我觉得我应该能够做到这一点! 有人能解释一下我为什么会犯这些错误吗?我看到过几篇类似