You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA关联两张表失败:idsubscriber字段多可写映射异常

问题解决:JPA关联字段重复映射错误

错误原因

错误提示说得很清楚:subscriber.idsubscriber字段有多个可写映射。你在Subscriber类里犯了个典型错误——同时把这个字段做了两件事:

  1. 单独映射成普通的实体属性(带@Column注解)
  2. 又把它作为@OneToOne关联的外键(@JoinColumn)

JPA不允许同一个数据库字段被多个可写映射绑定,不然持久化时会搞不清该用哪个值更新字段。

修复步骤

1. 修正Subscriber类的映射

直接删掉重复的idsubscriber普通属性映射就行,或者如果非要保留这个属性的读取功能,就把它标记为只读。推荐优先保留关联映射,通过关联对象访问字段:

修改后的Subscriber关键代码:

@Entity
@Table(name = "subscriber")
@XmlRootElement
// 省略NamedQueries部分
public class Subscriber implements Serializable {

    // 省略其他属性...

    // 删掉原来的idsubscriber普通属性
    // @Basic(optional = false)
    // @Column(name = "idsubscriber", nullable = false, length = 50)
    // private String idsubscriber;

    @OneToOne(targetEntity = Deon.class, cascade = CascadeType.ALL)
    @JoinColumn(name = "idsubscriber", referencedColumnName = "idsubscriber")
    private Deon deon;

    // 顺便把getItems/setItems改个合理的名字,和属性名对应上:
    public Deon getDeon() {
        return deon;
    }

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

    // 省略其他方法...
}

如果非要保留idsubscriber属性的读取,就把它改成只读:

@Column(name = "idsubscriber", insertable = false, updatable = false)
private String idsubscriber;

2. 修正Main类的JPQL错误

你的JPQL有俩问题:

  • 属性名大小写错了:s.Deon要写成s.deon(Java属性名是小写的)
  • 查询返回的是Object[]数组(存的是name和price两个值),不是Subscriber对象,强转会直接报错

修改后的Main代码:

// 查name和price的写法
List<Object[]> resultList = em.createQuery("SELECT s.name, d.price FROM Subscriber s JOIN s.deon d").getResultList();
for (Object[] row : resultList) {
    String name = (String) row[0];
    Integer price = (Integer) row[1];
    System.out.println(name + " -- " + price);
}

如果要查完整的Subscriber并关联Deon,用FETCH JOIN:

List<Subscriber> ll = em.createQuery("SELECT s FROM Subscriber s JOIN FETCH s.deon d").getResultList();
for (Subscriber f : ll) {
    System.out.println(f.getName() + " -- " + f.getDeon().getPrice());
}

3. 可选:加双向关联(如果需要)

要是需要从Deon反向查Subscriber,就在Deon类里加对应注解:

@Entity
@Table(name = "deon", catalog = "mngp", schema = "")
// 省略其他部分
public class Deon implements Serializable {

    // 省略其他属性...

    @OneToOne(mappedBy = "deon")
    private Subscriber subscriber;

    // 加getter和setter
    public Subscriber getSubscriber() {
        return subscriber;
    }

    public void setSubscriber(Subscriber subscriber) {
        this.subscriber = subscriber;
    }

    // 省略其他方法...
}

总结

核心就是解决同一个数据库字段的重复可写映射问题,要么删重复属性,要么标记为只读。另外注意JPQL的语法细节,别搞混属性大小写和查询结果类型。

内容的提问来源于stack exchange,提问作者Adm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:35:36