Home > Enterprise >  How to Embed a List of Specialized Classes Into an Entity
How to Embed a List of Specialized Classes Into an Entity

Time:11-14

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;
}
  • Related