【问题标题】:"org.hibernate.TypeMismatchException: Provided id of the wrong type" when using @OneToOne for a bi-directional relation“org.hibernate.TypeMismatchException:提供了错误类型的 id”当使用 @OneToOne 进行双向关系时
【发布时间】:2017-09-11 16:03:00
【问题描述】:

当两个类中的复合主键相同时,我无法成功使用@OneToOne:

@Entity
public class One implements Serializable {
    private static final long serialVersionUID = 1L;
    @EmbeddedId
    private OnePK onePK;
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "one")
    private Two two;
    //... constructors, getters and setters
}

@Entity
public class Two implements Serializable {
    private static final long serialVersionUID = 1L;
    @EmbeddedId
    private TwoPK twoPK;
    @JoinColumns({
        @JoinColumn(name = "P_ID", referencedColumnName = "P_ID", insertable = false, updatable = false),
        @JoinColumn(name = "L_ID", referencedColumnName = "L_ID", insertable = false, updatable = false)})
    @OneToOne(optional = false)
    private One one;
    //... constructors, getters and setters
}

@Embeddable
public class OnePK implements Serializable {
    @Basic(optional = false)
    @Column(name = "P_ID")
    private BigInteger dId;
    @Basic(optional = false)
    @Column(name = "L_ID")
    private BigInteger lId;
    //... constructors, getters and setters
}

@Embeddable
public class TwoPK implements Serializable {
    @Basic(optional = false)
    @Column(name = "P_ID")
    private BigInteger dId;
    @Basic(optional = false)
    @Column(name = "L_ID")
    private BigInteger lId;
    //... constructors, getters and setters
}

当我按原样使用上面的源代码时,我得到:

12:56:04,021 警告 [org.apache.cxf.phase.PhaseInterceptorChain] (默认任务 83)应用程序 {http://services.webservices.*****.******.com/}ObjectManagerService#{http://services.webservices.*****.******.com/}getAllObjects 已经抛出异常,现在展开:org.apache.cxf.interceptor.Fault: java.lang.IllegalArgumentException: org.hibernate.TypeMismatchException:为 com.******.*****..**********.两个。预期:类 com.******.*****..********.TwoPK,上课了 com.******.*****.**.********.OnePK at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:162) 在 org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.createFault(AbstractJAXWSMethodInvoker.java:267) 在

当我使用同一个类 (OnePK) 作为两个类(一和二)的主键时,我得到:

11:44:35,735 警告 [org.apache.cxf.phase.PhaseInterceptorChain] (默认任务 83)拦截器 {http://services.webservices.*****.******.com/}ObjectManagerService#{http://services.webservices.*****.******.com/}getAllObjects 已经抛出异常,现在展开:org.apache.cxf.interceptor.Fault: 编组错误:在对象图中检测到循环。这将 导致无限深的 XML : One[ onePK=OnePK[ dId=3151, lId=426 ] ] -> 二[ twoPK=OnePK[ dId=3151, lId=426 ] ] -> 一[ onePK=OnePK[ dId=3151, lId=426]]在 org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:266) 在 org.apache.cxf.jaxb.io.DataWriterImpl.write(DataWriterImpl.java:238) 在 org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor.writeParts(AbstractOutDatabindingInterceptor.java:118) 在

使用@PrimaryKeyJoinColumns 没有帮助,我使用了this answerthis tutorial,我得到了相同的错误消息。使用 @MapsId 没有帮助,我得到“org.hibernate.exception.GenericJDBCException:无法准备语句”。也许根本原因是this unfixed bug of Hibernate。我发现的唯一解决方法是删除第一次出现的@OneToOne 和类“One”中的字段“two”,但是当我删除此实例时,One 实例包含的 Two 实例不再被删除一,这就是我使用 CascadeType.ALL 的原因。

这个 JPA 源代码是由 Netbeans 8 自动生成的。我有点没办法了。有没有办法让它正常工作?这真的是Hibernate的限制吗?是否有另一种 JPA 实现正确处理这种情况?

【问题讨论】:

    标签: java hibernate jakarta-ee jpa-2.0 type-mismatch


    【解决方案1】:

    我认为问题出在@JoinColumn 映射中使用的name 属性,在Two 类中,name 使用的值与referencedColumnName 相同。

    事实上,Two 类已经从其TwoPk 类中嵌入了P_IDL_ID 属性,因此当您使用相同的名称name = "P_ID"name = "L_ID" 时,您不能同时映射这两个类因为这些属性已经在这个Entity 中所以你应该指定不同的名字:

    @JoinColumns({
        @JoinColumn(name = "OneP_ID", referencedColumnName = "P_ID", insertable = false, updatable = false),
        @JoinColumn(name = "OneL_ID", referencedColumnName = "L_ID", insertable = false, updatable = false)})
    @OneToOne(optional = false)
    private One one;
    

    注意:

    如果您为 PK 使用两个不同的类,为什么在两个类中使用相同的属性名称,最好在 OnePkTwoPk 中使用不同的名称将它们标识为:

    OnePk 类中分别为oneDIdoneLId,在TwoPk 类中分别为twoDIdtwoLId,这将使事情变得更好、更容易阅读、识别和映射。

    【讨论】:

    • 好的,我要试一试。谢谢。
    • 实际上,我不能在 Java 源代码中更改这些名称,因为我不允许在 SQL 表中更改它们,它们必须匹配:s
    • 嗯,你可以在 Java 中给它们不同的名称,并在 @Column 注释中使用相同的名称,但无论如何这不是重点,是否更改了 @JoinColumns 配置?
    【解决方案2】:

    起初,我通过调用this method 来增加Oracle UCP 中的TTL 连接超时,以消除GenericJDBCException。一些请求的执行时间过长,而允许保持连接使用的时间过短。

    其次,我使用同一个名为 OnePK 的类作为类 One 和 Two 的主键。

    第三,我将@XmlTransient添加到方法getOne()之前的类二中,以修复XML序列化中的循环。

    第四,我修改了我的管理器,以便他们调用 Two.setOne(final One one) 以便在不使用 Web 服务的情况下为调用持久层的源代码公开完整的对象(Two 的实例)。

    最后,我使用@MapsId修复了一些类似的情况,但主键更简单,仅由一列组成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-18
      • 1970-01-01
      • 2022-10-05
      • 2012-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多