【问题标题】:Composite Key with JPA and Hibernate使用 JPA 和 Hibernate 的复合键
【发布时间】:2021-10-14 12:17:42
【问题描述】:

在这段代码中,我尝试使用该模型类生成一个复合键,但是当我执行 post 方法时会引发异常。

我使用 postgres 作为数据库。然后我需要休眠自动生成“RA”和Idprojeto。

模型 ID 类

   @Data
   @EqualsAndHashCode(onlyExplicitlyIncluded = true)
   @AllArgsConstructor
   @NoArgsConstructor
   class ProjetoId implements Serializable{
   Long idProjeto;
   Long ra;
  }

模型实体

@Entity
@Data
@IdClass(ProjetoId.class)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Table(name = "projeto", schema = "public")
public class Projeto {

@EqualsAndHashCode.Include
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_projeto")
private Long idProjeto;

@Valid
@ConvertGroup(from = Default.class, to = ValidationGroups.ClienteId.class)
@NotNull
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "id_cliente")
private Cliente cliente;

@Valid
@NotNull
@ElementCollection
private List<ProdutoToProjeto> produtos = new ArrayList<>();

@EqualsAndHashCode.Include
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ra")
private Long ra;

@JsonProperty(access = JsonProperty.Access.READ_ONLY)
@Enumerated(EnumType.STRING)
@Column(name = "situacao")
private StatusProjeto situacao;

@JsonProperty(access = JsonProperty.Access.READ_ONLY)
@Column(name = "data_criacao")
private LocalDate dataRegistro;

public void finalizar() {
    if(naoPodeSerFinalizado()) {
        throw new ProjetoException("Projeto não pode ser finalizado");
    }
    setSituacao(StatusProjeto.APROVADO);
}

public void cancelar() {
    if(naoPodeSerFinalizado()) {
        throw new ProjetoException("Projeto não pode ser cancelado");
    }
    setSituacao(StatusProjeto.RECUSADO);
}

public boolean podeSerFinalizado() {
    return StatusProjeto.PEDENTE.equals(getSituacao());
}

public boolean naoPodeSerFinalizado() {
    return !podeSerFinalizado();
}

}

错误

   java.lang.IllegalArgumentException: Can not set java.lang.Long field com.ciasense.apiciasense.model.ProjetoId.ra to org.hibernate.id.IdentifierGeneratorHelper$2
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) ~[na:na]
    at java.base/java.lang.reflect.Field.set(Field.java:778) ~[na:na]

【问题讨论】:

    标签: java hibernate spring-data-jpa spring-annotations composite-primary-key


    【解决方案1】:

    如果您只使用 DB SEQUENCE 作为自动生成类型,那么复合键可以工作。否则,您必须编写自定义键生成器并在插入之前为复合键的两个字段分配值。

    @EqualsAndHashCode.Include
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id_projeto")
    private Long idProjeto;
    
    @EqualsAndHashCode.Include
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "ra")
    private Long ra;
    

    【讨论】:

    • 谢谢,这就是问题所在,hibernate 有一个错误,它不会使用@GenerationType.IDENTITY 生成复合键
    【解决方案2】:

    如果我理解,你想做一个关键组合? 如果是,你有两件事要做:

    1- 像你一样用@IdClass 注释你的类,并将@Id 放在你想用你的键和Equals 和HashCode 方法链接的属性上(你的IDE 很容易生成它)。 (这件事已经为你做好了)

    2- 在您的存储库中,您必须像普通密钥一样定义您的密钥 例子:(好像不行,是extends类中的“ProjetoId”)

    @Repository
    public interface ProjetoRepository extends JpaRepository<Projeto, ProjetoId> {
        List<Projeto> findByDataRegistro(Date date);
    }
    

    你也可以去看baeldung,比我解释的更详细。

    https://www.baeldung.com/jpa-composite-primary-keys

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-03
      • 2020-02-19
      • 2021-06-15
      • 2011-03-20
      • 1970-01-01
      • 2012-01-06
      • 2018-02-02
      • 2011-05-12
      相关资源
      最近更新 更多