1

Following this link

I would like to use OneToMany instead ManyToMany annotation, having middle class with composite key in it using Ebean. I have this error:

java.lang.RuntimeException: Error reading annotations for models.SoftwareTagPk

This is my SoftwareTagPk class:

@Embeddable
public class SoftwareTagPk  implements Serializable {

    @ManyToOne
    private Tag tag;

    @ManyToOne
    private Software software;

    ...
}

And SoftwareTag class:

@Entity
public class SoftwareTag extends Model {

    @EmbeddedId
    private SoftwareTagPk pk = new SoftwareTagPk();

    @Transient
    public Tag getTag() {
        return pk.getTag();
    }

    public void setTag(Tag aTag) {
        pk.setTag(aTag);
    }

    @Transient
    public Software getSoftware() {
        return pk.getSoftware();
    }

    public void setSoftware(Software aSoftware) {
        pk.setSoftware(aSoftware);
    } 
}

Also in logs:

Error with association to [class models.Tag] from [models.SoftwareTagPk.tag]. Is class models.Tag registered?

How to fix it?

rtruszk
  • 3,902
  • 13
  • 36
  • 53
ses
  • 13,174
  • 31
  • 123
  • 226

1 Answers1

2

To make this code work you have to do:

  1. In your SoftwareTagPk class put only id's of Tag and Software
  2. Move @ManyToOne relations to SoftwareTag class
  3. Add @JoinColumn annotations with attributes updatable and insertable set to false.
  4. Override setters setTag and setSoftware in SoftwareTag class. In these setters you will rewrite id's to composite key.

Main idea of this solution is that SoftwareTag has composite key and @ManyToOne relations and they are mapped to the same collumns.

This is the code:

Tag.java

@Entity 
public class Tag extends Model {
    @Id
    private Integer id;

    @OneToMany(mappedBy="tag")
    public List<SoftwareTag> softwareTags;

    public Integer getId() {
        return id;
    }

    public void setId(Integer aId) {
        id=aId;
    }

    public static Finder<Integer,Tag> find = new Finder<Integer,Tag>(
        Integer.class, Tag.class
    ); 
} 

Software.java

@Entity 
public class Software  extends Model {
    @Id
    private Integer id;

    @OneToMany(mappedBy="software")
    public List<SoftwareTag> softwareTags;

    public Integer getId() {
        return id;
    }

    public void setId(Integer aId) {
        id=aId;
    }
}

SoftwareTag.java

@Entity
public class SoftwareTag extends Model {

    SoftwareTag() {
        pk = new SoftwareTagPk();       
    }

    @EmbeddedId
    private SoftwareTagPk pk = new SoftwareTagPk();

    @ManyToOne
    @JoinColumn(name = "tag_id", insertable = false, updatable = false)
    private Tag tag;

    @ManyToOne
    @JoinColumn(name = "software_id", insertable = false, updatable = false)
    private Software software;

    public Tag getTag() {
        return tag;
    }

    public void setTag(Tag aTag) {
        tag = aTag;
        pk.tag_id = aTag.getId();
    }

    public Software getSoftware() {
        return software;
    }

    public void setSoftware(Software aSoftware) {
        software = aSoftware;
        pk.software_id = aSoftware.getId();
    }
}

SoftwareTagPk.java

@Embeddable
public class SoftwareTagPk implements Serializable {

    public Integer tag_id;

    public Integer software_id;

    @Override
    public int hashCode() {
        return tag_id + software_id;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) 
            return true;
        SoftwareTagPk pk = (SoftwareTagPk)obj;
        if(pk == null)
            return false;
        if (pk.tag_id.equals(tag_id) && pk.software_id.equals(software_id)) {
            return true;
        }
        return false;
    }
}
rtruszk
  • 3,902
  • 13
  • 36
  • 53