I am attempting to move a framework from hibernate3 to 4, this code worked in 3. The framework uses Interfaces to break the tight coupling of classes. Hence:
The Entity class is marked with @Entity and this instance uses and an instance of and @Embeddable defined as its interface, a very familiar pattern in Spring.
The code works fine in older versions of hibernate (V3), I am moving it to JPA2 and Hibernate 4
I realize that Hibernate would have a difficult time figuring out which implementation (concrete class) of the interface was being being mapped. Hence I understand the error, however, it does work on older versions.
Is this due to hibernate templates and mapping classes in older versions that are abstracted away in JPA2 & H4.
Is the best approach to simply create concrete implementations of all the interface implementing classes and define the @embedded as a concrete class.
Thanks much in advance.
// the Entity class HibAttribute
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
// Define a unique constraint on item, namespace, and localname
@Table(name="attribute", uniqueConstraints = {
@UniqueConstraint(columnNames={"itemid", "namespace", "localname"})})
// Define indexes on discriminator and key fields
@org.hibernate.annotations.Table(
appliesTo="attribute",
indexes={@Index(name="idx_attrtype", columnNames={"attributetype"}),
@Index(name="idx_attrname", columnNames={"localname"}),
@Index(name="idx_attrns", columnNames={"namespace"})})
@DiscriminatorColumn(
name="attributetype",
discriminatorType=DiscriminatorType.STRING,
length=16)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public abstract class HibAttribute extends HibAuditableObject implements java.io.Serializable, Attribute {
// Fields
@Embedded
@AttributeOverrides( {
@AttributeOverride(name="namespace", column = @Column(name="namespace", nullable = false, length=255) ),
@AttributeOverride(name="localName", column = @Column(name="localname", nullable = false, length=255) )
} )
private QName qname;
// The interface public interface QName {
/**
* Get local name
* @return local name
*/
public String getLocalName();
/**
* Set local name
* @param localName local name
*/
public void setLocalName(String localName);
/**
* Get namespace
* @return namespace
*/
public String getNamespace();
/**
* Set namespace
* @param namespace namespace
*/
public void setNamespace(String namespace);
/**
* Create copy of QName object.
* @return copy of current QName object
*/
public QName copy();
}
@Embeddable
public class HibQName implements QName {
public static final String DEFAULT_NAMESPACE = "org.osaf.cosmo.default";
private String namespace = null;
private String localName = null;
public HibQName() {}
/**
* Create new QName with specified namespace and local name.
* @param namespace namespace
* @param localName local name
*/
public HibQName(String namespace, String localName) {
this.namespace = namespace;
this.localName = localName;
}
// rest of class has been omitted ....... it is not needed to understand this issue.
The Stack trace: Caused by: org.hibernate.MappingException: Could not determine type for: org.timbre.model.QName, at table: attribute, for columns: [org.hibernate.mapping.Column(attributes_KEY)] at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:304) at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:288) at org.hibernate.mapping.IndexedCollection.validate(IndexedCollection.java:90) at org.hibernate.cfg.Configuration.validate(Configuration.java:1294) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1732) at org.hibernate.ejb.EntityManagerFactoryImpl.(EntityManagerFactoryImpl.java:88) at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904) ... 57 more