【问题标题】:Can't save entity Embeddable Id无法保存实体可嵌入 ID
【发布时间】:2019-03-01 00:07:58
【问题描述】:

我有EcranChamp 实体

@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;

...

还有EcranChampId

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

每次我尝试保存 EcranChamp 元素时都会出现以下错误

2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .wsmsDefaultHandlerExceptionResolver:无法转换请求元素:org.springframework.beans.ConversionNotSupportedException:无法转换属性值'java.lang.Long' 类型的属性'ecran' 需要类型'com.kepler.porttailclient.domain.model.Ecran';嵌套异常是 java.lang.IllegalStateException:无法将类型“java.lang.Long”的值转换为属性“ecran”所需的类型“com.kepler.porttailclient.domain.model.Ecran”:找不到匹配的编辑器或转换策略 2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .wsmsDefaultHandlerExceptionResolver:已解决由处理程序执行引起的异常:org.springframework.beans.ConversionNotSupportedException:无法转换类型的属性值'java.lang.Long' 为属性'ecran' 所需的类型'com.kepler.porttailclient.domain.model.Ecran';嵌套异常是 java.lang.IllegalStateException:无法将类型“java.lang.Long”的值转换为属性“ecran”所需的类型“com.kepler.porttailclient.domain.model.Ecran”:找不到匹配的编辑器或转换策略

【问题讨论】:

  • 您使用@IdClass 注释指定实体的id 类为EcranChampId。因此,您必须将@Id 字段设为EcramChampId。添加@Id 类型为EcranChamp 的两个字段不起作用。
  • 请为这个问题添加一个解决方案,我会尝试一下

标签: java spring spring-boot spring-data-jpa


【解决方案1】:

试试这样的:

@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 
}    

【讨论】:

  • 一个附加问题如何避免为ecranid_ecran 创建两个列。
  • 我不知道你的确切型号。但是您不需要在 EcramChamp 表中创建两列,只需字段 id_ecram。我认为 id_ecram 是您表中 PK/FK 的名称。编辑:我已经编辑我的答案更正确。 (@JoinColumn(name = "id_ecran")
  • 我可以用private Ecran id_ecran;替换可嵌入元素private Long id_ecran; 吗?!?
【解决方案2】:

你应该使用@EmbeddedId注解。

请将您的 EcranChampId 类更改为:

@Embeddable
public class EcranChampId implements Serializable  {  

    @ManyToOne
    private Champ champ;

    @ManyToOne
    private Ecran ecran;

    //getters and setters
}

并将您的 EcranChamp 类更改为:

@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);
    }
}

并像这样使用它:

public class Champ {

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

    //getters and setters
}

另外,如果EcranChampEcranChampId 没有其他字段,我建议您使用@ManyToMany 注释而不是EcranChamp 类,如下所示:

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
}

【讨论】:

    猜你喜欢
    • 2019-03-01
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多