I have an abstract entity using DiscriminatorColumn and is subclassed by various e开发者_开发问答ntites. Now, when I'm querying named query in the abstract class, it throws an error saying 'org.hibernate.InstantiationException Cannot instantiate abstract class or interface'. On analysis I found that the discriminator column is not appended in the generated native SQL itself. Following is a simplified version of the Entity Mapping:
package com.qz.test;
import javax.persistence.*;
/**
* User: r4rao
* Date: 7/18/11
* Time: 5:36 PM
*/
@Entity
@Table(schema = "ems", name = "nlt_content_profile")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "content_profile_type", discriminatorType = DiscriminatorType.STRING)
@NamedQueries({
@NamedQuery(name = "A.getProfilesForDelivery", query = "select pcp from A pcp where pcp.serviceId = :service_id ")
// @NamedQuery(name = "A.getProfilesByIdsForDelivery", query = "select pcp,s from A pcp,Subscription s LEFT JOIN FETCH s.client c LEFT JOIN FETCH c.operator where pcp.id in (:cp_ids) and pcp.service.id = :service_id and s.contentProfile.id = pcp.id and s.status in (:statuses) and (:use_timestamp = false or (:use_timestamp = true and s.beginningTime < :timestamp)))"),
// @NamedQuery(name = "A.removeUnusedContentProfiles", query = "DELETE FROM A pcp WHERE NOT EXISTS(SELECT 1 FROM Subscription sub WHERE sub.contentProfile.id = pcp.id)"),
// @NamedQuery(name = "A.getProfileIdsForDelivery", query = "select pcp.id from A pcp where pcp.service.id = :service_id and exists(select 1 from Subscription s where s.contentProfile.id = pcp.id and s.status in (:statuses))")
})
public abstract class A{
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "ContentProfileSeq")
@SequenceGenerator(name = "ContentProfileSeq", sequenceName = "ems.nlt_content_profile_seq")
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "service_id")
private Long serviceId;
public Long getServiceId() {
return serviceId;
}
public void setServiceId(Long serviceId) {
this.serviceId = serviceId;
}
}
package com.qz.test;
import javax.persistence.*;
/**
* User: r4rao
* Date: 7/18/11
* Time: 5:36 PM
*/
@Entity
public class B extends A {
@Column(name = "subscription_parameter")
private String param;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("B");
sb.append("{param='").append(param).append('\'');
sb.append('}');
return sb.toString();
}
}
I figured out it was due to a configuration mistake. Only abstract class was configured in persistence.xml while configuration for any concrete subsclass was missing. On adding configuration for concrete classes, this error was resolved.
Surprisingly, instead of throwing an appropriate error, it was not appending the filter clause using discriminator column in the generated query.
Your named query selects from A
which means "give me all instances of A
and its subclasses that match given criteria". There's no reason for Hibernate to filter on discriminator column since you're looking for all possible values of it anyway.
The error in question is most likely caused by incorrect data in the underlying database table - e.g. you have records with discriminator column value pointing to 'A'. Hibernate tries to instantiate A
class to hold them and cannot (since it's abstract), thus it throws an error.
精彩评论