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.  [ 5 posts ] 
Author Message
 Post subject: duplicated keys problem
PostPosted: Tue Sep 16, 2003 6:23 am 
Newbie

Joined: Tue Sep 16, 2003 6:12 am
Posts: 13
In a helpdesk application, all entity(s) have an id field well-mapped with an <id> tag in the Schema. Being this a table-per-entity mapping structure, each register of, in principle, any table should have a distinct value at the id column.
On the other hand, we aren't properly deleting registers when an entity is deleted at the application as we want to keep them for the history of the application itself. So what we do is to set a column value to 'D'. This way, when a register of a table (an entity at the end of the road) is active or exists, then, this column that all tables do have is set as an 'A' and changed when deleting.

Problem is when trying to retrive objects from a table where more than one register with the same id column have been inserted although there's only one column with the active value set to 'A'.
Why all this ?
The thing is that we get a ScrollableResult, scrollRes, with all the objects we need at a time and, of course, we have added the "where bla.active = 'A' " at the end of the query, hoping that this would have been enough in case of having duplicated keys/id's from old entries.
However, hibernate doesn't instantiate the objects of this collection until you actually ask for them. Hibernate only keeps the id's of these selected objects. So when doing the scrollRes.get(arg0) method, hibernate throws a plane query like "from Bla bla where bla.id = 'id' " to get the actuall object , and of course, an HibernateException ocurrs. Taking into account that we may have duplicated keys or id's, only discriminated by the active column by an A/D (active-deleted), but only one will be set to 'A' (active). How could we easly manage this persitance problem?

Thing is that we could have a real unique key, but we are very interested in not to. So what we want is basically have one sort-of-key, let's say 'code', and then another column called 'active'. At first, 'code' is being used as a key field. But whenever a persisten object/register is trying to be deleted, then, what we do is to change the value of the 'active' column from 'A' into 'D', in order to keep historical information. Now, this is what deleting is about in our application. But then, of course, we control that in case a 'code' column value appears more than once, only one of these entries will have the 'active' column value set to 'A'. This way, we pretend to retrive active registers/objects by querying with a "where active='A' " clause so we make sure that we are only getting objects with distinct values at 'code' field. And we do get the net.sf.hibernate.ScrollableResults, scrollRes, filled correctly. Problem is that what this scrollRes is really holind are only the 'code' values of this objects, and when calling the scrollRes.get(arg0) method, an hibernate query like "from Bla bla where bla.code = 'code' " is called, which in sql terms comes to be something like, "select * from table Bla where code = 'code' ". This throws an HibernateException when finding more than one 'code' colum with the same value; being the problem that in this automatical query, the clause "where active='A' " hasn't been attached.

So, i want to think that there must be a simple solution, such as, manipulating the mapping file or perhaps the configuration file; or maybe it's possible to twist this automaticla querys when needed or desired with some hibernate object. I don't know. I'm not an hibernate guru, but let me say that somehow i'm sure there must be a way. Problem is that i don't know what is this way....snif.

Well, if anyone have a solution, pleeeeeeeeease help.

Thanks a lot!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2003 7:53 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
First off, this is not a good relational design, from what I have heard. It sounds like you are saying that you are duplicating primary keys (actually not even a primary key, since it then is not unique). Primary keys, by definition, should be unique. If you tried to define this column as a primary key every RDBMS out there is going to complain about non-unique values. This is nothing to do with Hibernate. A relational model should always, always, always utilize unique keys. Even making the combination of "id" and your active column as unique won't work because it sounds like you might have multiple id and acitve=false combinations.

You could try to perform what you are looking for by using sub-classing. Define an ActiveEntity version of your Entity class. The map both in Hibernate, using the active column as the discriminator. This is doable, but by far the better way is to redesign your relational model to be more relational.

As you have not given any details about this, I don't know for sure, but another option might be to introduce an intermediary table which links the current active version of a record. Your entities could then link to this intermediary table. I have an entity which is sort of similiar in my domain model. It models the relation between a Course and a CourseRevision. The way I have set it up is that CourseRevision has a many-to-one relation to its Course (could also be bi-directional such that Course knows about its collection of revisions). Then Course maintains a manual many-to-one link to its currently active revision. Of course all CourseRevisions in my database table have a completely unique id.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2003 9:23 am 
Newbie

Joined: Tue Sep 16, 2003 6:12 am
Posts: 13
Thanks a lot. I'll think about it. Cheers!


Top
 Profile  
 
 Post subject: duplicate keys in legacy table
PostPosted: Mon Apr 11, 2005 5:16 pm 
Newbie

Joined: Tue Jan 04, 2005 11:06 am
Posts: 15
Hibernate 2.6

With all requisite disclaimers acknowledging the silliness of
non-unique keys...

I am stuck with a legacy table with non-unique keys. (The mapping follows).
The table is keyed with a composite id which is not unique. Basically, there
may be multiple time-stamped entries that server as descriptive lines for
a transaction.

When I do a query the size of results List is correct. However, when I
look at the records the one field that is not part of the composite id
is the same in all the records.

Originally, I was depending on default auto-generated (hbm2java) equals()
implementation which used only the fields within the id. It occurred to me
that this may not work because hibernate would not be able to
distinguish between cached entities that are different though they have the
same key.

I then added the 'description' field (the only non-key field) to the equals()
implementation (using use-in-equals) but this did not change a thing.

I have tried querying with both HQL within the mapping file as below
(ie. getCashHistoryDetailDescriptionsById) and using a Criteria object
which mimics the HQL below.

Am I doing something wrong? Given that I am stuck with table,
is there are workaround?

Thanks
Rob

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<!--
    Created by the Middlegen Hibernate plugin 2.1
    http://boss.bekk.no/boss/middlegen/
    http://www.hibernate.org/
-->
<class
    name="com.trustetc.model.CashHistoryDetailDescription"
    table="TRDHISS" >
    <meta attribute="class-description" inherit="false">
       @hibernate.class
        table="TRDHISS"
    </meta>
    <composite-id name="id"
                 class="com.trustetc.model.CashHistoryDetailDescriptionID" >
        <meta attribute="field-description" inherit="false">
           @hibernate.id
            generator-class="assigned"
        </meta>
        <meta attribute="use-in-equals">true</meta>
        <key-property
            name="accountNumber"
            column="TAN"
            type="int"
            length="7"
        >
            <meta attribute="field-description">
               @hibernate.property
                column="TAN"
            </meta>
        </key-property>
        <key-property
            name="postDate"
            column="PDATE"
            type="int"
          >
            <meta attribute="field-description">
               @hibernate.property
                column="PDATE"
            </meta>
        </key-property>
        <key-property
            name="userId"
            column="USERID"
            type="java.lang.String"
            length="10"
        >
            <meta attribute="field-description">
               @hibernate.property
                column="USERID"
            </meta>
        </key-property>
        <key-property
            name="postTime"
            column="PTIME"
            type="int"
            length="6"
        >
            <meta attribute="field-description">
               @hibernate.property
                column="PTIME"
            </meta>
        </key-property>
    </composite-id>
    <property
        name="description"
        column="DESC"
        type="java.lang.String"
        length="35"
    >
        <meta attribute="field-description">
           @hibernate.property
            column="DESC"
        </meta>
   <meta attribute="use-in-equals">true</meta>
    </property>
                                                                                     
    <!-- Associations -->
    <!-- derived association(s) for compound key -->
    <!-- end of derived association(s) -->
                                                                                     
</class>
    <query name="allCashHistoryDetailDescription">
        <![CDATA[from CashHistoryDetailDescription]]>
     </query>
     <query name="getCashHistoryDetailDescription">
        <![CDATA[from CashHistoryDetailDescription c where c.id.accountNumber = :accountNumber order by c.id.postDate desc ]]>
    </query>
     <query name="getCashHistoryDetailDescriptionsById">
        <![CDATA[from CashHistoryDetailDescription c where c.id.accountNumber = :accountNumber and c.id.userId = :user and c.id.postDate = :pdate and c.id.postTime = :ptime  order by c.id.postDate desc ]]>
    </query>
</hibernate-mapping>

_________________
Rob Gordon
SuffolkSoft, Inc.
Westby, WI


Top
 Profile  
 
 Post subject: duplicate keys in legacy table
PostPosted: Mon Apr 11, 2005 5:18 pm 
Newbie

Joined: Tue Jan 04, 2005 11:06 am
Posts: 15
Hibernate 2.6

With all requisite disclaimers acknowledging the silliness of
non-unique keys...

I am stuck with a legacy table with non-unique keys. (The mapping follows).
The table is keyed with a composite id which is not unique. Basically, there
may be multiple time-stamped entries that serve as descriptive lines for
a transaction detailed in another table.

When I do a query the size of results List is correct. However, when I
look at the records the one field (ie. description) that is not part of the composite id
is the same in all the records.

Originally, I was depending on default auto-generated (hbm2java) equals()
implementation which used only the fields within the id. It occurred to me
that this may not work because hibernate would not be able to
distinguish between cached entities that are different though they have the
same key.

I then added the 'description' field (the only non-key field) to the equals()
implementation (using use-in-equals) but this did not change a thing.

I have tried querying with both HQL within the mapping file as below
(ie. getCashHistoryDetailDescriptionsById) and using a Criteria object
which mimics the HQL below.

Am I doing something wrong? Given that I am stuck with table,
is there are workaround?

Thanks
Rob

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<!--
    Created by the Middlegen Hibernate plugin 2.1
    http://boss.bekk.no/boss/middlegen/
    http://www.hibernate.org/
-->
<class
    name="com.trustetc.model.CashHistoryDetailDescription"
    table="TRDHISS" >
    <meta attribute="class-description" inherit="false">
       @hibernate.class
        table="TRDHISS"
    </meta>
    <composite-id name="id"
                 class="com.trustetc.model.CashHistoryDetailDescriptionID" >
        <meta attribute="field-description" inherit="false">
           @hibernate.id
            generator-class="assigned"
        </meta>
        <meta attribute="use-in-equals">true</meta>
        <key-property
            name="accountNumber"
            column="TAN"
            type="int"
            length="7"
        >
            <meta attribute="field-description">
               @hibernate.property
                column="TAN"
            </meta>
        </key-property>
        <key-property
            name="postDate"
            column="PDATE"
            type="int"
          >
            <meta attribute="field-description">
               @hibernate.property
                column="PDATE"
            </meta>
        </key-property>
        <key-property
            name="userId"
            column="USERID"
            type="java.lang.String"
            length="10"
        >
            <meta attribute="field-description">
               @hibernate.property
                column="USERID"
            </meta>
        </key-property>
        <key-property
            name="postTime"
            column="PTIME"
            type="int"
            length="6"
        >
            <meta attribute="field-description">
               @hibernate.property
                column="PTIME"
            </meta>
        </key-property>
    </composite-id>
    <property
        name="description"
        column="DESC"
        type="java.lang.String"
        length="35"
    >
        <meta attribute="field-description">
           @hibernate.property
            column="DESC"
        </meta>
   <meta attribute="use-in-equals">true</meta>
    </property>
                                                                                     
    <!-- Associations -->
    <!-- derived association(s) for compound key -->
    <!-- end of derived association(s) -->
                                                                                     
</class>
    <query name="allCashHistoryDetailDescription">
        <![CDATA[from CashHistoryDetailDescription]]>
     </query>
     <query name="getCashHistoryDetailDescription">
        <![CDATA[from CashHistoryDetailDescription c where c.id.accountNumber = :accountNumber order by c.id.postDate desc ]]>
    </query>
     <query name="getCashHistoryDetailDescriptionsById">
        <![CDATA[from CashHistoryDetailDescription c where c.id.accountNumber = :accountNumber and c.id.userId = :user and c.id.postDate = :pdate and c.id.postTime = :ptime  order by c.id.postDate desc ]]>
    </query>
</hibernate-mapping>

_________________
Rob Gordon
SuffolkSoft, Inc.
Westby, WI


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

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.