简体   繁体   中英

Getting An Instance Of A Mapped Superclass With Hibernate EntityManager

I'm having some issues dealing with a Mapped Superclass in Hibernate. I have two applications, Product and Manufacturer that share a Common library but otherwise do not have any direct dependencies on each other. The Common lib has an abstract MappedSuperclass (common.domain.Manufacturer) that is the base entity. Manufacturer has a concrete class that extends the class in Common. There is no concrete version of the class in Product.

Originally, I was having trouble even getting this to compile since the common.domain.Manufacturer was not being recognized as an entity. I was able to fix that by defining the entity mapping via my ORM config (see: Handling Hibernate Persistence in Mapped Superclass for more details). While that did solve the compilation issues, unfortunately I'm still seeing errors at runtime. When I call entityManager.find() on the mapped superclass it fails with the error: org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: : com.tura.common.domain.Manufacturer

I thought perhaps I could use entityManager.getReference() instead of find(). That works as long as I don't actually need any information about the Manufacturer other than the primary key. Unfortunately, there are a few places in the code where I need some additional information about the Manufacturer. As soon as I access any field other than the Id it fails with the same error.

There are three options I can see right now, but they all come with drawbacks I would like to avoid. I could make the Common version of the class concrete, but that would defeat the purpose of having this hierarchy in the first place. I don't want the common version to get instantiated and potentially persisted. Only the Manufacturer application should be doing that. I could create a concrete class in the Product application, but that would require adding a DTYPE to the database that is meaningless outside of hibernate. The final, and worst, option would be to make Product and Manufacturer have a direct dependency. I'm not even considering that unless every other possibility is exhausted.

I feel like there must be some clean way of doing what I need. Any help would be greatly appreciated.

A mapped superclass isn't an entity. It's only a class that shares its mapping definition with its subclasses. You, therefore, can't select it with Hibernate or any other JPA implementation.

If you want to select the superclass in a query or define polymorphic associations, you should look at the table per class strategy . It maps each concrete entity class to its own database table. You can set that strategy by annotating your superclass with @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) , eg:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Manufacturer { ... }


@Entity
public class Product extends Manufacturer { ...}

In the next step, you need to decide if your superclass shall be abstract or not. Using the table per class strategy, you can make your superclass abstract. You will then not be able to instantiate and persist any objects of that class. But you can use them in your queries and association mappings. Hibernate then always returns the specific subclass.

You wrote that you would prefer to make the superclass abstract without having any concrete subclasses in one of your applications. That sounds like a questionable design decision because you wouldn't be able to use the superclass in that application. Hibernate wouldn't know any of the subclasses, and you wouldn't be able to select or persist them.

If you want to learn more about JPA's different options to map inheritance hierarchies, I recommend reading my in-depth guide about it: Inheritance Strategies with JPA and Hibernate – The Complete Guide

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM