Я провел некоторое исследование и прошел это руководство .
Вот моя структура сущностей:
@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<>();
}
Пример элемента 1:
@Entity
public class Coke extends Item{
@Column
private String cokeProperty;
@Column
private String cokeProperty2;
}
Пример элемента 2:
@Entity
public class Sprite extends Item{
@Column
private String spriteProperty;
@Column
private String spriteProperty2;
}
Класс изображения, используемый абстрактным классом Item:
@Entity
public class Picture {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
}
Все они имеют конструкторы, геттеры и сеттеры, иtoString переопределяет.Я делаю это потому, что мне нужна таблица для Items
, а затем отдельные таблицы для Coke
и Sprite
, каждая из которых содержит внешний ключ id
из Items_table
.Кроме того, я предполагаю, что это также создаст таблицу для Pictures
, которая также имеет внешний ключ от Items_table
.Однако я не могу понять, как реализовать Spring Boot и JPA для этого.Я думал, что это будет так же просто, как этот
Мой репозиторий для элементов с настроенной базой данных h2 в application.properties
@Repository
public interface ItemRepository<Item, Long>{
}
Мой Сервис, который реализует интерфейс 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);
} }
А потом мой контроллер, который принимает 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);
}
}
Но когда я POST
с Json Data, как
{
"name": "Toyota Civic 3 days sale!!",
"pictures": [
{
"name": "picture 1"
},
{
"name": "picture 2"
}
],
"cokeProperty": "sweet",
"cokeProperty2": "not healthy"
}
Я получаю эту ошибку:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Невозможно создать экземпляр com.example.demo.entities.product.Item
(никаких создателей, таких как конструкция по умолчанию, не существует): абстрактныйтипы либо должны быть сопоставлены с конкретными типами, иметь собственный десериализатор или содержать дополнительную информацию о типе в [Source: (PushbackInputStream);строка: 1, столбец: 1]
Я также попробовал другую стратегию для своего абстрактного класса:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
Все еще нет сигары.Та же ошибка.Может ли кто-нибудь объяснить мне, как правильно использовать Spring Boot и JPA для абстрактных сущностей, расширенных другими сущностями?