-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Overriding primary key attributes
PostPosted: Mon Apr 23, 2007 11:27 am 
Newbie

Joined: Mon Apr 23, 2007 6:49 am
Posts: 2
Hi there,

Here is a short background of our problem.

We are using the JPA implementation based on Hibernate Core 3.2 GA, Hibernate Annotations 3.3.0 GA and Hibernate EntityManager 3.3.0 GA.
We have an abstract class (a layer supertype) which encapsulates an embeddable primary key. There are two subclasses which inherit the primary key from the layer supertype. Each of the subclasses is mapped to a particular table. The names of the columns to which the primary keys of these classes are mapped are different in each table.

We then try to retrieve an instance of an entity bean by its identity, but keep getting an exception message which seems to relate to the fact that the primary key mapping cannot be overridden in the mapping of a subclass.

Our example is based on:

Hibernate Core 3.2 GA,
Hibernate Annotations 3.3.0 GA ,
Hibernate EntityManager 3.3.0 GA,
MS SQL 2000

Here is the primary key class we are using in our example:
Code:
package testing;

import java.io.*;

public final class IntegerIdentity implements Serializable, Comparable
{
    /**
     * The unique identifier.
     */
    private Integer id;
   
    /**
     * Initialises a new instance of the class.
     *
     * <p> This constructor is used exclusively by persistence provider.
     */
    private IntegerIdentity()
    {
        super();
    }
   
    /**
     * Initialises a new instance of the class with the specified parameters.
     *
     * @param id the unique identifier.
     * @throws NullPointerException if the value of {@code id} is {@code null}.
     */
    public IntegerIdentity(Integer id)
    {
        super();
       
        if(id == null)
            throw new NullPointerException("A non-null value is expected.");
       
        this.id = id;
    }
   
    /**
     * Returns the unique identifier.
     *
     * @return the unique identifier.
     */
    public Integer getId()
    {
        return id;
    }
   
    /**
     * Compares the current object with the specified object for equality.
     *
     * <p> This implementation is based on comparison between the {@code id} attribute of the current object
     * and the {@code id} attribute of the specified object according to the general equality requirements set
     * out in the {@code equals} method of the {@code Object} class.
     *
     * @param anObject the object to be compared with the current object.
     * @return {@code true} if the objects are equal, otherwise return {@code false}.
     */
    public boolean equals(Object anObject)
    {
        if(this == anObject)
            return true;
       
        if(anObject == null || !(anObject instanceof IntegerIdentity))
            return false;
       
        IntegerIdentity other = (IntegerIdentity)anObject;
        return (id == other.id || (id != null && id.equals(other.id)));
    }
   
    /**
     * Compares the current object with the specified object according to their natural ordering.
     *
     * <p> This implementation is based on comparison between the {@code id} attribute of the current object
     * and the {@code id} attribute of the specified object according to their numerical order and in
     * consistency with the {@code equals} method of the {@code Object} class.
     *
     * @param anObject the object to be compared with the current object.
     * @return the value of {@code -1} if the {@code id} attribute of the current object is less than the
     * {@code id} attribute of the specified object; the value of {@code 0} if the {@code id} attribute of the
     * current object is equal to the {@code id} attribute of the specified object; the value of {@code 1} if
     * the {@code id} attribute of the current object is greater than the {@code id} attribute of the specified
     * object.
     */
    public int compareTo(Object anObject)
    {
        IntegerIdentity other = (IntegerIdentity)anObject;
        return id.compareTo(other.id);
    }
   
    /**
     * Returns the hash code of the object.
     *
     * @return the hash code of the object.
     */
    public int hashCode()
    {
        return id != null ? id.hashCode() : 0;
    }
   
    /**
     * Returns the string representation of the object.
     *
     * <p> The string representation of the object contains the unique identifier.
     *
     * @return the string representation of the object.
     */
    public String toString()
    {
        return getClass().getName() + "(id=" + id + ")";
    }
}

Here is the abstract class (a layer supertype) we are using in our example:
Code:
package testing;

import java.io.*;

public abstract class LayerSuperType implements Serializable
{
    protected IntegerIdentity identifer;
   
    protected LayerSuperType()
    {
        super();
    }
}

Here is the first subclass of a layer supertype we are using in our example:
Code:
package testing;

public final class C extends LayerSuperType
{
    public C()
    {
        super();
    }
   
    public String toString()
    {
        return "identifer = " + identifer.getId();
    }
}

Here is the second subclass of a layer supertype we are using in our example:
Code:
public class D extends LayerSuperType
{
    public D()
    {
        super();
    }
   
    public String toString()
    {
        return "identifer = " + identifer.getId();
    }
}

Here is the testing class we are using in our example:
Code:
package testing;

import com.dkib.cpds.zion.common.entity.processed.fitch.*;
import javax.persistence.*;

public final class Main
{
    public static void main(String[] args)
    {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence");
        EntityManager em = emf.createEntityManager();
       
        try
        {
            EntityTransaction tr = em.getTransaction();
            tr.begin();
           
            C c = em.find(C.class, new IntegerIdentity(1));
            System.out.println(c);
           
            D d = em.find(D.class, new IntegerIdentity(1));
            System.out.println(d);           
           
            tr.commit();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            em.close();
        }
    }
}

Here is the first table we are using in our example:
Code:
CREATE TABLE [c] (
[c_id] [int] NOT NULL ,
[col1] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
CONSTRAINT [PK_c] PRIMARY KEY  CLUSTERED
(
  [c_id]
)  ON [PRIMARY]
) ON [PRIMARY]
GO

Here is the second table we are using in our example:
Code:
CREATE TABLE [d] (
[d_id] [int] NOT NULL ,
[col1] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
CONSTRAINT [PK_d] PRIMARY KEY  CLUSTERED
(
  [d_id]
)  ON [PRIMARY]
) ON [PRIMARY]
GO

Here is the mapping file we are using in our example:
Code:
<?xml version="1.0" encoding="UTF-8"?>

<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
                 version="1.0">
   
    <mapped-superclass class="testing.LayerSuperType"
                       access="FIELD"
                       metadata-complete="true">
        <attributes>
            <embedded-id name="identifer"/>
        </attributes>
    </mapped-superclass>
   
    <entity class="testing.C"
            access="FIELD"
            metadata-complete="true">
        <attribute-override name="identifer">
            <column name="c_id"
                    insertable="true"
                    updatable="true"/>
        </attribute-override>
    </entity>
   
    <entity class="testing.D"
            access="FIELD"
            metadata-complete="true">
        <attribute-override name="identifer">
            <column name="d_id"
                    insertable="true"
                    updatable="true"/>
        </attribute-override>
    </entity>

    <embeddable class="testing.IntegerIdentity" access="FIELD"/>

</entity-mappings>

Here is the exception stack of our example:
Code:
23-Apr-2007 14:09:56 org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 207, SQLState: S0003
23-Apr-2007 14:09:56 org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: Invalid column name 'id'.
23-Apr-2007 14:09:56 org.hibernate.event.def.DefaultLoadEventListener onLoad
INFO: Error performing load command
org.hibernate.exception.SQLGrammarException: could not load an entity: [testing.C#component[id]{id=1}]
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
        at org.hibernate.loader.Loader.loadEntity(Loader.java:1865)
        at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
        at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
        at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3038)
        at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:395)
        at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
        at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
        at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:179)
        at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
        at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
        at org.hibernate.impl.SessionImpl.get(SessionImpl.java:815)
        at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:175)
        at testing.Main.main(Main.java:53)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid column name 'id'.
        at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Unknown Source)
        at com.microsoft.sqlserver.jdbc.IOBuffer.processPackets(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerStatement.sendExecute(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteQuery(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(Unknown Source)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1778)
        at org.hibernate.loader.Loader.doQuery(Loader.java:662)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
        at org.hibernate.loader.Loader.loadEntity(Loader.java:1851)
        ... 13 more
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not load an entity: [testing.C#component[id]{id=1}]
        at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:630)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:195)
        at testing.Main.main(Main.java:53)
Caused by: org.hibernate.exception.SQLGrammarException: could not load an entity: [testing.C#component[id]{id=1}]
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
        at org.hibernate.loader.Loader.loadEntity(Loader.java:1865)
        at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
        at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
        at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3038)
        at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:395)
        at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
        at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
        at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:179)
        at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
        at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
        at org.hibernate.impl.SessionImpl.get(SessionImpl.java:815)
        at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:175)
        ... 1 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid column name 'id'.
        at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Unknown Source)
        at com.microsoft.sqlserver.jdbc.IOBuffer.processPackets(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerStatement.sendExecute(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteQuery(Unknown Source)
        at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(Unknown Source)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1778)
        at org.hibernate.loader.Loader.doQuery(Loader.java:662)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
        at org.hibernate.loader.Loader.loadEntity(Loader.java:1851)
        ... 13 more


We understand that the <attribute-override> feature used to map primary keys of our subclasses should allow the primary keys to be mapped to different columns, but this doesnt seem to be the case as proven by the exception above. This makes us wonder whether this is an error in the implementation or whether this type of overriding is not allowed at all.

If anyone could give us a hand with this problem we would really appreciate it.

Cheers


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.