views:

373

answers:

2

I'm trying to add a composite primary key to a class and having a bit of trouble. Here are the classes.

class User {
    private long id;
    ...
}

class Token {
    private User user;
    private String series;
    ...
}

I'm using the orm.xml to map the classes because they're actually part of a higher level API that I don't want to depend on JPA - it has a number of implementations.

Here it is:

...
<entity class="User">
    <attributes>
        <id name="id">
            <generated-value strategy="AUTO"/>
        </id>
        ...
    </attributes>
</entity>

<entity class="Token">
    <id-class class="TokenPK"/>
    <attributes>
        <id name="series"/>
        <id name="user"/>
        <many-to-one name="user"/>
    </attributes>
</entity>

Finally to make it all work, I've created the TokenPK class and it looks like this:

public class TokenPK implements Serializable {

    private String series;
    private User user;

    public TokenPK() {
    }

    public TokenPK(String series, User user) {
        this.series = series;
        this.user = user;
    }

    public String getSeries() {
        return series;
    }

    public void setSeries(String series) {
        this.series = series;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        RememberMeTokenPK that = (TokenPK) o;

        if (!series.equals(that.series)) return false;
        if (!user.equals(that.user)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = series.hashCode();
        result = 31 * result + user.hashCode();
        return result;
    }
}

The problem I'm having is that Hibernate is complaning that it can't create the mysql tables because 'BLOB/TEXT column 'user' used in key specification without a key length'.

My issue is actually that the columns are being stored as BLOBs in the first place. Until I put the id-class in it was working just fine, user was linked via it's id. How can I make Hibernate use the long value for the user's id it was using as the primary key?

Updated orm.xml:

<entity class="Token">
    <id-class class="TokenPK"/>
    <attributes>
        <id name="series"/>
        <id name="user">
            <column name="userId"/>
        </id>
        <many-to-one name="user">
            <join-column name="userId" insertable="false" updatable="false"/>
        </many-to-one>
    </attributes>
</entity>
+1  A: 

Define the composite key with String series and int userId, and specify a join-column id for the User in Token. I think you will also have to add insertable="false", updatable="false".

 <composite-id name="TikenPK" class="yourpackage.TokenPK"> 
        <key-property name="series" column="series" type="string" />
        <key-property name="userId" column="userId" type="integer"/>
       </composite-id>
Bozho
I've tried this and I get an error `org.hibernate.AnnotationException: Unable to find properties (userId) in entity annotated with @IdClass:Token`
Andrew McCall
add @Column (or map in xml as <column) the fields in TokenPK
Bozho
I'm not sure what you mean, I've updated the orm.xml (see above) and it's now giving me `org.hibernate.AnnotationException: @Column(s) not allowed on a @ManyToOne property: Token.user`
Andrew McCall
Check my update
Bozho
Is that JPA or Hibernate config? I've been looking at the hibernate tests and it seems to be possible with annotations just can't figure out how to do it in the XML file.
Andrew McCall
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-compositeid
Bozho
Yeah, looks like my problems all stem from this not working with JPA 1 - So I'll either have to move to JPA 2 or straight hibernate - thanks for the help.
Andrew McCall