Consider the following hierarchy, where entities WidgetA
and WidgetB
extend an abstract Widget
superclass:
@Entity
@In
Your objects and annotations look fine to me. I was able to take them, save a widget to a database, and fetch it out without a problem.
I think the the problem is in your data. Hibernate is probably finding a row in the Widget
table that does not have a corresponding row in any of the sub class tables, and is therefore trying to create an instance of the superclass, and failing.
With InheritanceType.JOINED
, you can either specify a discriminator, or let it do it for you (I believe by checking whether a row with that ID exists in the subclass table). But either way, you have to check your data to make sure there's not an entry in the super class table without a matching subclass row.
As a rule, I support @ben75's recommendation that you do explicitly specify @Discriminator
for class hierarchies. It's better to have control over your discriminator values, so that later code changes don't alter the values in unexpected ways.
Hibernate supports that query just fine, and will happily return an instance of the correct subclass. Without knowing what it is in the Spring Data implementation that is trying to make an instance of Widget, you should be able to just declare the query and have it run it directly, rather than using the parser.
public interface WidgetDAO extends JpaRepository<Widget, Long> {
@Query("select w from Widget w where w.serialNumer = ?1")
public Widget findBySerialNumber(String serialNumber);
}
It seems you didn't specify a discriminator explicitly for your widget hierarchy. I think you can try to define it explicitly because Spring Data will manipulate bytecode to generate the queries, and so I suspect SpringData need to have those values explicitely defined.
Additionally in subclasses you need to indicate the discriminator value for each subclass.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="WIDGET_TYPE")
public abstract class Widget implements Serializable {
@Column(name="serialNumber", length=64, nullable=false, unique=true)
private String serialNumber;
...
-
@Entity
@DiscriminatorValue("A")
public class WidgetA extends Widget implements Serializable {
...
-
@Entity
@DiscriminatorValue("B")
public class WidgetB extends Widget implements Serializable {
...