1

I've got two tables A and B with simple PK's.

@Entity
public class A { 
    @Id
    public int idA;
}

@Entity
public class B { 
    @Id
    public int idB;
}

I want to map a new association class AB that simply stores the relations between A and B, with composite PK idA+idB. AB doesn't have any extra columns, just the relation between idA and idB.

Is it possible to map AB using a single class? I want to avoid having to create a new ABId class just to use it as @IdClass or @EmbeddedId in AB, and I don't want to map this with a @ManyToMany association on A or B.

Xavi López
  • 27,550
  • 11
  • 97
  • 161

2 Answers2

3

Why do you want to map such a join table? Just use a ManyToMany association between A and B. This join table will then be handled automatically when you'll add/remove a B to/from the list of Bs contained in A.

See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#d0e11402

If you really want to do that, then just map the two IDs with the @Id notation. The primary class will be the entity class itself (which must be serializable), as explained in the hibernate reference documentation. Note that this is Hibernate-specific.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I want to do this because I've already got `A` and `B` mapped, they are static data that is really unlikely to change (and with lots of other such unmapped relations). So is `AB`. I've got a list of `idA`'s retrieved at startup stored in a spring bean, and I'd like to just build a Map> at startup. This table would avoid having to do joins or subqueries with `AB` at startup when recovering the list of `A`'s. I'll probably end up not mapping it with Hibernate and querying it with native SQL. – Xavi López Oct 17 '11 at 12:15
  • Great, that's just what I needed. I don't think it works on `hibernate-annotations 3.3.1.GA` though, per [HHH-4327](https://hibernate.onjira.com/browse/HHH-4327). – Xavi López Oct 17 '11 at 12:31
  • As expected, I just tested this, and the SQL query hibernate throws for `session.createCriteria(AB.class).list()` is this: `select this_.ID_A as COD2_248_0_ from AB this_`. All `idB` fields are null. I'll try updating to the latest version. – Xavi López Oct 17 '11 at 13:17
  • In a test with `hibernate-core 3.6.7.Final`, this worked as expected. I'm not upgrading, however. I'll stick to @IdClass with an inner static class. – Xavi López Oct 17 '11 at 15:28
0

It would be nice if @JBNizet 's suggestion worked. Unfortunately, there's an old bug which makes it impossible to adopt it in the version I'm using (3.3.1-GA)

I've finally sorted this out by defining an inner static ID class and using it as @IdClass:

@Entity
@Table(name="TABLE_AB")
@IdClass(value=ClassAB.ClassABId.class)
public class ClassAB implements Serializable {

    private String idA;
    private String idB;

    @Id
    public String getIdA(){ return idA; }
    public void setIdA(String idA){ this.idA = idA; }

    @Id
    public String getIdB(){ return idB; }
    public void setIdB(String idB){ this.idB = idB; }

    static class ClassABId implements Serializable {
        private String idA;
        private String idB;

        @Column(name="ID_A")
        public String getIdA(){ return idA; }
        public void setIdA(String idA){ this.idA = idA; }

        @Column(name="ID_B")
        public String getIdB(){ return idB; }
        public void setIdB(String idB){ this.idB = idB; }

        // HashCode(), equals()
    }
}

This way I don't have to define a new public class, and I don't have to modify the mappings file to include the ID class.

Community
  • 1
  • 1
Xavi López
  • 27,550
  • 11
  • 97
  • 161