简体   繁体   English

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

[英]Can't get MappedSuperClass abstract entity to work with Spring Boot and JPA

I've done some research and I've gone through this guide . 我进行了一些研究,并仔细阅读了本指南

Here is my structure of entities: 这是我的实体结构:

@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<>();

}

Sample Item 1: 样本项目1:

@Entity
public class Coke extends Item{

    @Column
    private String cokeProperty;

    @Column
    private String cokeProperty2;
}

Sample Item 2: 样本项目2:

@Entity
public class Sprite extends Item{

    @Column
    private String spriteProperty;

    @Column
    private String spriteProperty2;
}

Picture class used by abstract class Item: 抽象类使用的图片类

@Entity
public class Picture {

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

    private String name;
}

All of these have constructors, getters and setters, and toString overrides. 所有这些都有构造函数,getter和setter以及toString覆盖。 I'm doing this because I want a table for Items , and then separate tables for Coke and Sprite , each containing a foreign key id from Items_table . 之所以这样做,是因为我想要一个用于Items的表,然后为CokeSprite分离一个表,每个表都包含Items_table中的外键id Additionally, I assume that it would also create a table for Pictures that also has a foreign key from Items_table . 另外,我假设它还将为Pictures创建一个表,该表也具有Items_table的外键。 What I can't figure out, however, is how to implement Spring Boot and JPA for this. 但是,我不知道的是如何为此实现Spring Boot和JPA。 I thought it would be as simple as this 我以为就这么简单

My Repository for items which has a configured h2 database in application.properties 我的资料库,用于在application.properties中具有已配置的h2数据库的项目

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

My Service which implements ItemService interface and takes in an ItemRepository bean: My Service,它实现ItemService接口并接收一个ItemRepository bean:

@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);
}    }

And then my Controller which takes in an ItemService bean: 然后我的Controller接收了ItemService bean:

@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);
    }
}

But when I POST with Json Data like 但是,当我POST与JSON数据一样

{
    "name": "Toyota Civic 3 days sale!!",
    "pictures": [
      {
        "name": "picture 1"
      },
      {
        "name": "picture 2"
      }
    ],
    "cokeProperty": "sweet",
    "cokeProperty2": "not healthy"
}

I get this error: 我收到此错误:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.example.demo.entities.product.Item (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information at [Source: (PushbackInputStream); com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造com.example.demo.entities.product.Item实例(不存在像默认构造那样的创建者):抽象类型要么需要映射到具体类型,要么具有自定义解串器,或在[来源:(PushbackInputStream);中包含其他类型信息; line: 1, column: 1] 行:1,列:1]

I've also tried another strategy on my abstract class: 我还在抽象类上尝试了另一种策略:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

Still no cigar. 还是没有雪茄。 Same error. 同样的错误。 Can someone enlighten me on the proper way of using Spring Boot and JPA for abstract entities that are extended by other entities? 有人可以启发我对其他实体扩展的抽象实体使用Spring Boot和JPA的正确方法吗?

javax.persistence's @MappedSuperClass is not directly related with this issue. javax.persistence的@MappedSuperClass与该问题没有直接关系。 As the error message points it out, the cause is in jackson-databind. 正如错误消息指出的那样,原因在jackson-databind中。

Since Item is an abstract class, Jackson cannot determine which concrete class it should instantiate in order to deserialize the entity from JSON. 由于Item是一个抽象类,Jackson无法确定应实例化哪个具体类以便从JSON反序列化实体。 That is why Item must be annotated with references to the implementations: 这就是为什么必须在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

}

A small change will also be necessary in the JSON, because it should point to the implementing type: 在JSON中也需要进行少量更改,因为它应该指向实现类型:

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

Please note that @JsonTypeInfo provides a few choices for how to bind it with the implementation, not necessarily with the "type" field. 请注意, @JsonTypeInfo提供了几种选择,以将其与实现绑定,而不必与“类型”字段绑定。 There are various examples and documentation available about it. 有许多有关它的示例和文档。

A short test allows shows that Item is now deserialized properly: 简短的测试允许显示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)

But this change would not be enough to make things work for your service. 但是,这种更改不足以使事情为您的服务工作。 As @Rujal Shrestha already mentions in his comment, there are also issues with repositories definitions and missing autowiring. 正如@Rujal Shrestha在评论中已经提到的,存储库定义和自动装配缺失也存在问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 @MappedSuperclass 不是 JPA 中的 @Entity 吗? - @MappedSuperclass is not an @Entity in JPA? Spring Boot 无法通过 findAll 或 findByColumnName 方法获取关系实体 - Spring Boot Can't get the relation entity with findAll or findByColumnName method 带有 JPA 实体的 Spring Boot 第二个存储库查询很好,但无法无错误地保存 - Spring boot with JPA entity Second repository query is fine but can't save with no error Jpa + Spring 引导实体过滤器 - Jpa + Spring Boot Entity filter 在 Spring Boot 中使用 JPA 保存时,有没有办法获得“刷新”保存的实体? - Is there a way to get a 'refreshed' saved entity when saving with JPA in Spring boot? 无法让 Resilience4j @RateLimiter 与 Spring 引导一起使用 - Can't get Resilience4j @RateLimiter to work with Spring Boot 创建一个Spring Boot应用程序并且无法使@autowired工作 - Creating a spring boot app and can't get @autowired to work 如果@MappedSuperclass无法与查询和实体管理器一起使用,那又有什么意义呢? - What is the point of @MappedSuperclass if it can't be used with queries and the entity manager? Spring 引导不起作用自定义 JPA 请求 - Spring Boot doesn't work custom JPA request Spring Boot应用程序中的JPA多对多关系不起作用 - JPA many to many relation in Spring Boot app doesn't work
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM