java - 如何正确处理与 JPA 的 FK 关系
问题描述
我这里有这个实体关系图: https ://i.imgur.com/V05i6nK.png
我正在尝试做这个项目。我已经完成了所有的课程,建立了关系和其他一切。
但是一旦我尝试运行并创建一个新用户,我就会收到以下错误:
外键 (FK3w0xeq6jk6vt2vi1fydpci0y9:T_PAGAMENTO [CD_CORRIDA])) 的列数必须与引用的主键 (T_CORRIDA [CD_PASSAGEIRO,CD_MOTORISTA,CD_CORRIDA]) 的列数相同
我试图建立这些关系,但我没有什么不同。
@Entity
@Table(name="T_CORRIDA")
@SequenceGenerator(name="sq_corrida", sequenceName="SEQ_T_CORRIDA", allocationSize=1)
public class Corrida {
@Id
@GeneratedValue(generator="sq_corrida", strategy = GenerationType.SEQUENCE)
@Column(name="CD_CORRIDA")
private int cd_corrida;
@Column(name="DS_ORIGEM", length = 150, nullable= false)
private String ds_origem;
@Column(name="DS_DESTINO", length= 150, nullable= false)
private String ds_destino;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="DT_CORRIDA")
private Calendar dt_corrida;
@Column(name="VL_CORRIDA", nullable= false)
private float vl_corrida;
@Id
@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="CD_MOTORISTA")
private Motorista motorista;
@Id
@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="CD_PASSAGEIRO")
private Passageiro passageiro;
@OneToMany(mappedBy="corrida", cascade= CascadeType.PERSIST)
private List<Pagamento> listaPagamento;
@Entity
@Table(name="T_MOTORISTA")
@SecondaryTable(name="T_DADOS_MOTORISTA", pkJoinColumns={@PrimaryKeyJoinColumn(name="NR_CARTEIRA")})
public class Motorista {
@Id
@Column(name="NR_CARTEIRA", nullable= false)
private int nr_carteira;
@Column(name="NM_MOTORISTA", length= 150, nullable= false)
private String nm_motorista;
@Temporal(TemporalType.DATE)
@Column(name="DT_NASC")
private Calendar dt_nasc;
@Lob
@Column(name="FT_CARTEIRA")
private byte[] ft_carteira;
@Enumerated(EnumType.STRING)
@Column(name="DS_GENERO")
private TipoSexo ds_genero;
@ManyToMany(cascade=CascadeType.PERSIST)
@JoinTable(name="T_VEICULO_MOTORISTA",
joinColumns=@JoinColumn(name="NR_CARTEIRA"),
inverseJoinColumns=@JoinColumn(name="CD_VEICULO"))
private List<Veiculo> listaVeiculo;
@OneToMany(mappedBy="motorista")
private List<Corrida> corridasMotorista;
@Column(name="NR_BANCO", table="T_DADOS_MOTORISTA")
private int banco;
@Column(name="NR_AGENCIA", table="T_DADOS_MOTORISTA")
private int agencia;
@Column(name="NR_CONTA", table="T_DADOS_MOTORISTA")
private int conta;
@Entity
@Table(name="T_PASSAGEIRO")
@SequenceGenerator(name="seq_passageiro", sequenceName="SEQ_T_PASSAGEIRO", allocationSize=1)
public class Passageiro {
@Id
@Column(name="cd_passageiro")
@GeneratedValue(generator="seq_passageiro", strategy=GenerationType.SEQUENCE)
private int cd_passageiro;
@Column(name="NM_PASSAGEIRO", nullable= false, length= 100)
private String nm_passageiro;
@Temporal(TemporalType.DATE)
@Column(name="DT_NASCIMENTO", nullable=false)
private Calendar dt_nascimento;
@Enumerated(EnumType.STRING)
@Column(name="DS_GENERO")
private TipoSexo ds_genero;
@OneToMany(mappedBy="passageiro")
private List<Corrida> corridaPassageiro;
@Entity
@Table(name="T_PAGAMENTO")
@SequenceGenerator(name="seq_pgto", sequenceName="SEQ_T_PGTO", allocationSize=1)
public class Pagamento {
@Id
@Column(name="CD_PAGAMENTO", nullable= false)
@GeneratedValue(generator="seq_pgto", strategy=GenerationType.SEQUENCE)
private int cd_pagamento;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="DT_PAGAMENTO", nullable= false)
private Calendar dt_pagamento;
@Column(name="VL_PAGAMENTO", nullable= false)
private float vl_pagamento;
@Enumerated(EnumType.STRING)
@Column(name="DS_PAGAMENTO", nullable = false)
private TipoPagamento ds_forma_pagamento;
@ManyToOne
@JoinColumn(name="CD_CORRIDA")
private Corrida corrida;
我只想知道我做错了什么以及为什么我会收到外键错误,如何正确设置这些键。提前感谢!
解决方案
通过将@Id
注释添加到字段 cd_corrida、motorista 和 cd_corrida,您已指定实体 Corrida 具有复合 PK。在这种情况下,Pagamento 必须在 T_PAGAMENTO 表中的相应 3 列上指定连接。
但是,由于您为 Corrida 中的一个字段使用自动生成的序列,@ID
因此不需要复合 PK,因为 Corrida 只能由该字段唯一标识:
@Id
@GeneratedValue(generator="sq_corrida", strategy = GenerationType.SEQUENCE)
@Column(name="CD_CORRIDA")
private int cd_corrida;
然后,您可以删除其他 2 个@Id
注释。ID 不需要匹配任何 PK 列定义的数据库:它必须是唯一的,并且通过为 cd_corrida 指定一个序列,然后实体管理器可以将其单独用作标识符。
推荐阅读
- r - 是否可以将存储在 N*1 矩阵中的单词转换为 R 中的单个句子?
- java - Jflex 中的模式
- google-signin - 生产服务器上的 Google 登录不同
- tsql - 根据通用名称填充列行(子查询仅返回一个值)
- html - :before 和 :after 不显示网站何时被推送
- elasticsearch - 将聚合文档计数作为渗透查询的一部分的最佳方法
- javascript - 正则表达式匹配匹配集后的所有内容,匹配集除外
- php - Laravel 从在 API 级别更新它的用户中验证唯一的移动设备?
- ios - iOS:使用 Grabba 读取非接触式 VISA 智能卡数据
- python - 正则表达式:赛后拿走一切