3

I have EcranChamp entity

@Entity
@IdClass(EcranChampId.class)
public class EcranChamp {

@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ecran")
Ecran ecran;


@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "champ")
Champ champ;

...

And EcranChampId

@Embeddable
public class EcranChampId implements Serializable  {    
private Champ champ;  
private Ecran ecran;
...

Every time i am trying to save an EcranChamp element i have this following error

2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to convert request element: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran': no matching editors or conversion strategy found 2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran': no matching editors or conversion strategy found

Yagami Light
  • 1,756
  • 4
  • 19
  • 39
  • 1
    You specified that the id class for your entity is `EcranChampId` using the `@IdClass` annotation. So you must make the `@Id` field of type `EcramChampId`. Adding two fields with `@Id` with types `Ecran` and `Champ` does not work. – Jesper Sep 25 '18 at 11:22
  • please add a solution to this question and i will try it – Yagami Light Sep 25 '18 at 11:24
  • 1
    See [How to create and handle composite primary key in JPA](https://stackoverflow.com/questions/13032948/how-to-create-and-handle-composite-primary-key-in-jpa) – Jesper Sep 25 '18 at 11:35

2 Answers2

2

Try something like this:

@Entity
@Table(name = "<entity name>")
public class EcranChamp {

    @EmbeddedId
    @AttributeOverrides({ @AttributeOverride(name = "id_ecran", column = @Column(name = 
        "<column name>", nullable = false)),
    @AttributeOverride(name = "id_champ", column = @Column(name = "<column name>", nullable = false)) })
    EcranChampId id

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_ecran")
    Ecran ecran;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_champ")
    Champ champ; 
   //getters & setters 
 }   


@Embeddable
public class EcranChampId implements Serializable  {   
  @Column(name = "id_champ", nullable = false) 
  private Long id_champ; 
  @Column(name = "id_ecran", nullable = false)  
  private Long id_ecran; 
  //getters & setters 
}    
Seba López
  • 739
  • 1
  • 9
  • 18
  • An addtionnal question how to avoid the création of two colmun one for `ecran` and for `id_ecran` – Yagami Light Sep 25 '18 at 12:31
  • I don't know your exactly model. But you don't need to create two column in your EcramChamp table, just the field id_ecram. The id_ecram I supossed that was the name of the PK/FK in your table. EDIT: I have edit my answer for being more correctly. (@JoinColumn(name = "id_ecran") – Seba López Sep 25 '18 at 12:39
  • Can i replace Embeddable element `private Long id_ecran; ` by `private Ecran id_ecran;` ?!? – Yagami Light Sep 25 '18 at 12:43
0

You shoud use @EmbeddedId annotation.

Please, change your EcranChampId class to this:

@Embeddable
public class EcranChampId implements Serializable  {  

    @ManyToOne
    private Champ champ;

    @ManyToOne
    private Ecran ecran;

    //getters and setters
}

And change your EcranChamp class to this:

@Entity
@Table(name = "champ_has_ecran_table_name")
@AssociationOverrides({
    @AssociationOverride(name = "pk.champ", joinColumns = @JoinColumn(name = "champ_id"))
    @AssociationOverride(name = "pk.ecran", joinColumns = @JoinColumn(name = "ecran_id"))
})
public class EcranChamp {

    @EmbeddedId
    private EcranChampId pk;

    public EcranChamp() {
        pk = new EcranChampId();
    }

    public EcranChampId getPk() {
        return pk;
    }

    public void setPk(EcranChampId pk) {
        this.pk = pk;
    }

    @Transient
    public Champ getChamp() {
        return pk.getChamp();
    }

    public void setChamp(Champ champ) {
        pk.setChamp(champ);
    }

    @Transient
    public Ecran getEcran() {
        return pk.getEcran();
    }

    public void setChamp(Ecran ecran) {
        pk.setEcran(ecran);
    }
}

And use it like this:

public class Champ {

    @OneToMany(mappedBy = "pk.champ")
    private Collection<EcranChamp> ecranChamps;

    //getters and setters
}

Also, if EcranChamp or EcranChampId has no other fields i will recommend you to use @ManyToMany annotation instead EcranChamp class like this:

public class Champ {

    @ManyToMany
    @JoinTable(
        name = "champ_has_ecran_table_name",
        joinColumns = @JoinColumn(name = "champ_id", referencedColumnName = "id", nullable = false),
        inverseJoinColumns = @JoinColumn(name = "ecran_id", referencedColumnName = "id", nullable = false)
    )
    private Collection<Ecran> ecrans;

    //getters and setters
}
Artiow
  • 351
  • 1
  • 9