2

I have an Entity class that makes use of two of its fields as primary key(together). Here is what I'm trying. I already have the database so I cannot just stop following this path and create a single primary key.

 @Entity
public class Account {
    private String description;
    private AccountPk id;

    public Account (String description) {
    this.description = description;
    }

    protected Account() {
    }

    @EmbeddedId
    public AccountPk getId() {
        return this.id;
    }
    public String getDescription() {
        return this.description;
    }
    public void setId(AccountPk id) {
        this.id = id;
    }
    public void setDescription(String description) {
        this.description = description;
    }
}

Then I have another supporting class

    public class AccountPk {
    private String code;
    private Integer number;
    public AccountPk() {
    }

    public String getCode() {
        return this.code;
    }
    public Integer getNumber() {
        return this.number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public int hashCode() {
        int hashCode = 0;
        if( code != null ) hashCode ^= code.hashCode();
        if( number != null ) hashCode ^= number.hashCode();
        return hashCode;
    }

    public boolean equals(Object obj) {
        if( !(obj instanceof AccountPk) ) return false;
        AccountPk target = (AccountPk)obj;
        return ((this.code == null) ?
        (target.code == null) :
        this.code.equals(target.code))
        && ((this.number == null) ?
        (target.number == null) :
        this.number.equals(target.number));
    }
}

What I'm having a problem is the mapper class, Account.hbm.xml which looks like

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class
name="hello.Account"
table="MESSAGES">
<id
name="id"
column="MESSAGE_ID">
<generator class="increment"/>
</id>
<property
name="description"
column="DESCRIPTION"/>
</class>
</hibernate-mapping>

I am sure this xml file is the culprit but I don't know how to do it in a right way. So, I'll appreciate your help on this.

Abraham
  • 603
  • 7
  • 19
  • I think this post can help: http://stackoverflow.com/questions/6405746/mapping-manytomany-with-composite-primary-key-and-annotation – danny.lesnik May 03 '12 at 10:59

1 Answers1

3

Use <composite-id> instead of <id>, for example like this:

<composite-id>
    <key-property name="firstId" column="FIRST_ID_COL" type="..." /> 
    <key-property name="secondId" column="SECOND_ID_COL" type="..." /> 
</composite-id>

By the way, you can't use a generator with a composite id. You have to generate the id yourself. (Anyway, a generator for a composite key normally doesn't make sense. Which of the key components should it generate and when?)

Johanna
  • 5,223
  • 1
  • 21
  • 38
  • Thanks for your reply guys, but as I've come to understand from what I already read, composite-key is when there is a cardinality relationship between two or more entities. Besides, there is no '@CompositeId' annotation that I can use on my entity? In my case, there is only one table that is not supposed to have the same combination of data in two of its columns. The '@EmbeddedId' way is suggested to be a good way by many people in the hibernate community; only if I know how to configure it. – Abraham May 03 '12 at 12:51
  • `composite-id>` you always can use when your primary key is made of two ore more columns. There is not necessarily a cardinality relationship. -- Don't ask me about annotations, I never use them, but you might find some information [here](http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#d0e2177). Xml mapping files seem to be the easier solution. – Johanna May 03 '12 at 13:07