2

I want to map the following classes with Hibernate JPA:

enter image description here

My code looks like this:

   @Entity
    public class Grid{
        @Id
        @GeneratedValue
        private Long id;
        @Column(unique=true)
        private String name;
        private String location;
        private BigDecimal costsPerCPUMinute;

        @OneToMany(mappedBy="grid")
        private List<Membership> mem;

            public List<Membership> getMem() {
             return mem;
            }
            public void setMem(List<Membership> mem) {
            this.mem = mem;
            }

@Entity
public class User extends Person{
    @Column(nullable=false, unique=true)
    private String username;
    @Column(length=16,columnDefinition="BINARY(16)") 
    private byte[] password;

    @OneToMany(mappedBy="user")
    private List<Membership> mem;

    public List<Membership> getMem() {
        return mem;
    }
    public void setMem(List<Membership> mem) {
        this.mem = mem;
    }


@SuppressWarnings("serial")
@Entity
public class Membership  implements Serializable{

    private Date registration;
    private Double discount;    
    @Id
    @ManyToOne
    private Grid grid;
    @Id
    @ManyToOne
    private User user;

    public Grid getGrid() {
        return grid;
    }
    public void setGrid(Grid grid) {
        this.grid = grid;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }

Unfortunately, I get the following Exception:

Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: dst1.model.Membership.grid in dst1.model.Grid.mem

As far as I understand the message, grid cannot be found in Membership. But as you can see in de code, there definitly is a variable named grid in the Membership class.

Does anybody has an idea whats going wrong?

Update: As suggested in the comments, I also tried to change the Membership Class by using IDClass or EmbeddedID. The EmbeddedID version looks like this:

 @SuppressWarnings("serial")
    @Entity    
public class Membership  implements Serializable{

        private Date registration;
        private Double discount;    
        @EmbeddedId
        private MembershipPK membershipPK;

        public Membership(){};

        public MembershipPK getMembershipPK() {
            return membershipPK;
        }

        public void setMembershipPK(MembershipPK membershipPK) {
            this.membershipPK = membershipPK;
        }

    @SuppressWarnings("serial")
    @Embeddable
    public class MembershipPK implements Serializable{
        @ManyToOne
        private Grid grid;
        @ManyToOne
        private User user;


        public Grid getGrid() {
            return grid;
        }
        public void setGrid(Grid grid) {
            this.grid = grid;
        }
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
    }

Unfortunately, I still get the same exception.

Update 2: I will rewrite all three classes from scratch tomorrow evening and update this post if that changes anything.

punkyduck
  • 669
  • 2
  • 9
  • 17
  • The Membership class has two @Id fields, this feels wrong. I don't think this is the correct way to map a composite primary key. – Sebastien Mar 26 '12 at 13:33
  • Nothing wrong with 2 Id fields, *as long as accompanied by* IdClass. – DataNucleus Mar 26 '12 at 13:58
  • I tried to change from 2 id fields to an EmbeddedId, but still the same problem. – punkyduck Mar 26 '12 at 14:06
  • If you have control over the tables, you can create an auto-generated id and mark the others as natural ids. http://stackoverflow.com/questions/1212058/how-to-make-a-composite-primary-key-java-persistence-annotation/1252317#1252317 – kevingallagher Mar 26 '12 at 16:16
  • Hello, I'm having the same problem, already tried the solutions presented here before and still no good results. Did you eventually end up fixing this? If you did, how did you do it? Thank you in advance! – Tadeu Marques Sep 03 '14 at 12:05

2 Answers2

1

You should be able to use something like

@Embeddable
public class MembershipId
{
       protected Grid grid;
       protected User user;
}

@Entity
public class Membership {
    @EmbeddedId
    MembershipId id;
}

@Entity
public class User {
    @OneToMany(mappedBy="id.user")
    private Set<Membership> memberships = new HashSet<Membership>();
}
Stefan Kögl
  • 4,383
  • 1
  • 27
  • 34
  • I too have had no luck with the dot ('.') notation. I had to timebox a fix for this problem and ended up changing the db schema to have generated (surrogate) keys, thereby circumventing the composite-FK-mapping-to-composite-PK problem. – Cornel Masson Jul 12 '12 at 10:21
  • @skoegl. Thanks for the answer but I got exception when I try to mapped some "Non Lazy Collection" field on this way. Can you please look at http://stackoverflow.com/questions/23312951/jpa-and-hibernate-initialize-non-lazy-collections-error . Thanks in advance. – Channa Apr 26 '14 at 16:23
0

From the top of my head: shouldn't this be rather

public class MembershipId implements Serializable {
  private Grid grid;
  private User user;

  // immutable constructor, getters, equals, and hashCode
}

@Entity
@IdClass(MembershipId.class)
public class Membership implements Serializable {

  @Id @ManyToOne
  private Grid grid;

  @Id @ManyToOne
  private User user;

  // rest of class
}

Edit: What the exception is telling you is that your Grid class has a field named mem and that the entity represented by this field needs a grid field, but doesn't have one. Here is where your Grid.mem needs a grid field:

@Entity
public class Grid{
...
  @OneToMany(mappedBy="grid")
  private List<Membership> mem;

This mapping can only work if there is a property grid in Membership.class. If you hide the grid inside the IdClass, Grid.mem can't find it. You might try this:

@Embeddable
public class MembershipId implements Serializable {
  private Grid grid;
  private User user;

  // immutable constructor, getters, equals, and hashCode
}

@Entity
public class Membership implements Serializable {

  @EmbeddedId
  private MembershipId id;

  @ManyToOne
  private Grid grid;

  @ManyToOne
  private User user;

  // rest of class
}
wallenborn
  • 4,158
  • 23
  • 39