If you aren’t using table inheritance on the database side (e.g. super class table with descriminator column), AFAIK, and based off reading the JPA tutorial, this can’t be done (i.e. simply using @MappedSuperclass
annotation for your abstract class)
Mapped superclasses cannot be queried and cannot be used in EntityManager or Query operations. You must use entity subclasses of the mapped superclass in EntityManager or Query operations. Mapped superclasses can’t be targets of entity relationships
Note, the JPA repository abstraction uses an EntityManager under the hood. I did a simple test, and what you will get (in the case of Hibernate implementation) an “IllegalArgumentException : not an entity AbstractClass
“
On the other hand, if you do use table inheritance, then you can use the abstract type. I know you said “with just the minimal change” (and I guess my short answer is I don’t think it’s possible – probably for the reasons you guessed), so I guess the rest of this answer is for other inquiring minds 😉
An example of a table inheritance strategy would be something like this (disclaimer: this is not the correct visualization for erd inheritance, but MySQL Workbench doesn’t support it, but what I have below forward engineered the model to MYSQL the way it needs to be)
Where CountryCatalog
has a FK/PK reference to the AbstractCatalog
table pk (id). The AbstractCatalog
table has a descriminatorColumn
that will be used to determine to which subtype the supertype occurrence is related.
In terms of how you would code that, it would look something like
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="descriminatorColumn")
@Table(name="AbstractCatalog")
public abstract class AbstractCatalog {
@Id
private long id;
...
}
@Entity
@Table(name = "CountryCatalog")
public class CountryCatalog extends AbstractCatalog {
// id is inherited
...
}
public interface AbstractCatalogRepository
extends JpaRepository<AbstractCatalog, Long> {
}
@Repository
public class CountryCatalogServiceImpl implements CountryCatalogService {
@Autowired
private AbstractCatalogRepository catalogRepository;
@Override
public List<CountryCatalog> findAll() {
return (List<CountryCatalog>)(List<?>)catalogRepository.findAll();
}
@Override
public CountryCatalog findOne(long id) {
return (CountryCatalog)catalogRepository.findOne(id);
}
}
Basically, in conclusion, what you are trying to do won’t work if you don’t have table inheritance. The class type for the repository needs to be an entity. If your tables aren’t set up this way for inheritance, it just comes down to whether or not you want to change the tables. It may be a bit much just to avoid multiple repositories though.
Some references I used are here and here
Note: Everything in this answer is tested against Hibernate provider