Home > Software engineering >  Unable to join two table JPA
Unable to join two table JPA

Time:09-28

I have two table and I try to join use column idsubscriber but show some error.

Class Subscriber:

@Entity
@Table(name = "subscriber")
@XmlRootElement
@NamedQueries({
      @NamedQuery(name = "Subscriber.findAll", query = "SELECT s FROM Subscriber s")
    , @NamedQuery(name = "Subscriber.findById", query = "SELECT s FROM Subscriber s WHERE s.id = :id")
    , @NamedQuery(name = "Subscriber.findByIdsubscriber", query = "SELECT s FROM Subscriber s WHERE s.idsubscriber = :idsubscriber")
    , @NamedQuery(name = "Subscriber.findByName", query = "SELECT s FROM Subscriber s WHERE s.name = :name")
    , @NamedQuery(name = "Subscriber.findByPhone", query = "SELECT s FROM Subscriber s WHERE s.phone = :phone")
    , @NamedQuery(name = "Subscriber.findByLoc", query = "SELECT s FROM Subscriber s WHERE s.loc = :loc")
    , @NamedQuery(name = "Subscriber.findByNum", query = "SELECT s FROM Subscriber s WHERE s.num = :num")
    , @NamedQuery(name = "Subscriber.findByType", query = "SELECT s FROM Subscriber s WHERE s.type = :type")
    , @NamedQuery(name = "Subscriber.findByDate", query = "SELECT s FROM Subscriber s WHERE s.date = :date")})
public class Subscriber implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private Integer id;
    @Basic(optional = false)
    @Column(name = "idsubscriber", nullable = false, length = 50)
    private String idsubscriber;
    @Basic(optional = false)
    @Column(name = "name", nullable = false, length = 200)
    private String name;
    @Basic(optional = false)
    @Column(name = "phone", nullable = false, length = 45)
    private String phone;
    @Basic(optional = false)
    @Column(name = "loc", nullable = false, length = 255)
    private String loc;
    @Basic(optional = false)
    @Column(name = "num", nullable = false)
    private int num;
    @Column(name = "type")
    private Integer type;
    @Basic(optional = false)
    @Column(name = "date", nullable = false, length = 50)
    private String date;
    
     @OneToOne(targetEntity = Deon.class, cascade = CascadeType.ALL)
    @JoinColumn(name = "idsubscriber",referencedColumnName="idsubscriber")
    private Deon deon;

    public Subscriber() {
    }

    public Subscriber(Integer id) {
        this.id = id;
    }

    public Subscriber(Integer id,String name, String phone,int type, String loc, int num, String date) {
        this.id = id;
        this.name = name;
        this.phone = phone;
        this.type=type;
        this.loc = loc;
        this.num = num;
        this.date = date;
    }
    
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getIdsubscriber() {
        return idsubscriber;
    }

    public void setIdsubscriber(String idsubscriber) {
        this.idsubscriber = idsubscriber;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }
    public Deon getItems() {
        return deon;
    }

    public void setItems(Deon deon) {
        this.deon = deon;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash  = (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Subscriber)) {
            return false;
        }
        Subscriber other = (Subscriber) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "hiber.Subscriber[ id="   id   " ]";
    }
    
}

Class Deon:

@Entity
@Table(name = "deon", catalog = "mngp", schema = "")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Deon.findAll", query = "SELECT d FROM Deon d")
    , @NamedQuery(name = "Deon.findById", query = "SELECT d FROM Deon d WHERE d.id = :id")
    , @NamedQuery(name = "Deon.findByIdsubscriber", query = "SELECT d FROM Deon d WHERE d.idsubscriber = :idsubscriber")
    , @NamedQuery(name = "Deon.findByPrice", query = "SELECT d FROM Deon d WHERE d.price = :price")
    , @NamedQuery(name = "Deon.findBySprice", query = "SELECT d FROM Deon d WHERE d.sprice = :sprice")
    , @NamedQuery(name = "Deon.findByDate", query = "SELECT d FROM Deon d WHERE d.date = :date")})
public class Deon implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private Integer id;
    @Basic(optional = false)
    @Column(name = "idsubscriber", nullable = false, length = 50)
    private String idsubscriber;
    @Basic(optional = false)
    @Column(name = "price", nullable = false)
    private int price;
    @Column(name = "sprice")
    private Integer sprice;
    @Basic(optional = false)
    @Column(name = "date", nullable = false, length = 50)
    private String date;

    public Deon() {
    }

    public Deon(Integer id) {
        this.id = id;
    }

    public Deon(Integer id, String idsubscriber, int price, String date) {
        this.id = id;
        this.idsubscriber = idsubscriber;
        this.price = price;
        this.date = date;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getIdsubscriber() {
        return idsubscriber;
    }

    public void setIdsubscriber(String idsubscriber) {
        this.idsubscriber = idsubscriber;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public Integer getSprice() {
        return sprice;
    }

    public void setSprice(Integer sprice) {
        this.sprice = sprice;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash  = (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Deon)) {
            return false;
        }
        Deon other = (Deon) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "another.Deon[ id="   id   " ]";
    }
    
}

Class Main:

List<Subscriber>ll=em.createQuery("SELECT s.name,d.price FROM Subscriber s join s.Deon d ").getResultList();
                 for(Subscriber f: ll){
                      System.out.println(f.getName()  " -- "  f.getItems().getPrice());
                 }

Error:

org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [subscriber.idsubscriber].  Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[deon]
Descriptor: RelationalDescriptor(hiber.Subscriber --> [DatabaseTable(subscriber)])

CodePudding user response:

Do not use join here rather than you can rewrite that query as follows because hibernate/JPA do mapping itself for you.

SELECT s.name , s.deon.price from subscriber s

CodePudding user response:

Issue from the error is you have the Subscriber "idsubscriber" column mapped with two separate java properties - the "deon" OneToOne property and the "idsubscriber" String property.

If you meant for the Deon table to have a foreign key column that holds the subscriber ID value, try something more like:

public class Subscriber implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    .. //(all other properties mapped the same, excluding idsubscriber!)
    @OneToOne(mappedBy="subscriber", cascade = CascadeType.ALL)
    private Deon deon;
    ..
}


public class Deon implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private Integer id;
    //If you really need a string for this:
    @Column(name = "idsubscriber", nullable = false, length = 50, updatable=false, insertable=false)
    private String idsubscriber;
    @JoinColumn(name = "idsubscriber",referencedColumnName="idsubscriber")
    private Subscriber subscriber;//this reference is what now controls and sets the "idsubscriber" fk column.
    .. //other properties, mappings and methods unchanged
}
  • Related