Here below is a simple model for a pet shop...
Pet Class
@Getter
@Setter
@EqualsAndHashCode
@Embeddable
public abstract class Pet {
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "name", nullable = false)
private String name;
}
Cat Class
@Getter
@Setter
@EqualsAndHashCode
@Embeddable
public class Cat extends Pet {
@Column(name = "call")
private String call;
}
PetShop Class
@Entity
@Table(name = "pet_shop")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class PetShop {
@Column(name = "id", nullable = false)
private Long id;
@ElementCollection
@CollectionTable(
name = "pets",
joinColumns = @JoinColumn(name = "pet_id", referencedColumnName = "id"))
private List<Pet> pets= new ArrayList<>();
}
PetShopRepository Interface
public interface PetShopRepository
extends JpaRepository<PetShop, Long> {}
... and here is how to create a PetShop
with at least one Pet
:
final Pet pet = new Cat();
pet.setName("cat");
pet.setCall("meow");
final PetShop petShop = new PetShop();
petShop.getPets().add(pet);
petShopRepositiry.save(petShop);
So far so good... but when I try to retrieve the PetShop
...
final PetShop petShop = petShopRepository.findById(shopId)
.orElseThrow(() -> new ShopNotFoundException(shopId));
I always get the following error:
org.springframework.orm.jpa.JpaSystemException: Cannot instantiate abstract class or interface:
: com.mytest.persistence.model.Pet; nested exception is org.hibernate.InstantiationException:
Cannot instantiate abstract class or interface: : com.myTest.persistence.model.Pet
Of course the message is clear... but I'm wondering whether it is possible to have a collection of pets, each potentially referencing a different specialized class?
CodePudding user response:
I think if you use @JsonIgnore in the Petshop class. Use @OneToMany relationship annotation then it should work. Like this
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.Lazy, mappedBy = "pets")
@JsonIgnore
private List<Pet> pets= new ArrayList<>();
CodePudding user response:
To make it work, I just made class Pet
concrete (removed abstract
):
@Getter
@Setter
@EqualsAndHashCode
@Embeddable
public class Pet {
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "name", nullable = false)
private String name;
}