Pergunta

É possível em JPA simples ou extensões de JPA + Hibernate para declarar uma chave composta, onde um elemento da chave composta é uma sequência?

Esta é a minha classe composta:

@Embeddable
public class IntegrationEJBPk implements Serializable {

    //...


    @ManyToOne(cascade = {}, fetch = FetchType.EAGER)
    @JoinColumn(name = "APPLICATION")
    public ApplicationEJB getApplication() {
        return application;
    }


    @Column(name = "ENTITY", unique = false, nullable = false, insertable = true, updatable = true)
    public String getEntity() {
        return entity;
    }

    @GeneratedValue(strategy = GenerationType.AUTO, generator = "INTEGRATION_ID_GEN")
    @SequenceGenerator(name = "INTEGRATION_ID_GEN", sequenceName = "OMP_INTEGRATION_CANONICAL_SEQ")
    @Column(name = "CANONICAL_ID", unique = false, nullable = false, insertable = true, updatable = true)
    public String getCanonicalId() {
        return canonicalId;
    }

    @Column(name = "NATIVE_ID", unique = false, nullable = false, insertable = true, updatable = true)
    public String getNativeId() {
        return nativeId;
    }

    @Column(name = "NATIVE_KEY", unique = false, nullable = false, insertable = true, updatable = true)
    public String getNativeKey() {
        return nativeKey;
    }

    //...
}

Já fornecer os valores para application, entity, nativeId e nativeKey. Quero construir uma entidade como a abaixo:

IntegrationEJB i1 = new IntegrationEJB();
i1.setIntegrationId(new IntegrationEJBPk());
i1.getIntegrationId().setApplication(app1);
i1.getIntegrationId().setEntity("Entity");
i1.getIntegrationId().setNativeId("Nid");
i1.getIntegrationId().setNativeKey("NK");

E quando eu chamo em.persist(i1), eu quero que o canonicalId é gerado e é inserida a integração.

Isso é possível? Se assim for, qual é a maneira simples? (Eu não preferir usar as teclas fornecido pelo aplicativo ou SQL nativo).

Foi útil?

Solução

Eu acredito que isso não é possível com JPA simples.

Outras dicas

Usando @GeneratedValue para PKs compósitos não é especificado withi APP 2 spec.

A partir do JPA spec:

11.1.17 GeneratedValue Anotação

A anotação GeneratedValue prevê a especificação de estratégias de geração para os valores de chaves primárias. o GeneratedValue anotação pode ser aplicado a uma propriedade chave primária ou campo de uma entidade ou mapeados superclasse em conjunto com o Id anotação. [97] O uso da anotação GeneratedValue só é de ser apoiados para chaves primárias simples. Use do GeneratedValue anotação não tem suporte para as chaves primárias derivadas.

Note que, num cenário diferente, você pode ter uma entidade pai com uma PK simples (@ ID) que usa @GeneratedValue, e depois ter uma entidade filho que tem uma PK composta que inclui o ID gerado a partir do pai, mais outra coluna.

  • Dar à criança um relacionamento @ManyToOne à entidade-mãe, para que ele herda o ID gerado em uma coluna FK.
  • Em seguida, dar à criança uma PK composta, via @IdClass especificado contra a entidade, além de duas colunas @ id dentro da entidade.
@Entity
public class ParentEntity {
       @Id
       @GenerateValue(IDENTITY) // If using DB auto-increment or similar
       int id;

       // ...
}
@Entity
@IdClass(ChildId.class)
public class ChildEntity {
   // The child table will have a composite PK:
   // (parent_ID, child_name)
       @Id 
       @ManyToOne
       int parentEntity;
       @Id
       String childName;

       String favoriteColor;  // plus other columns

       // ...

}
// child Id attributes have the same name as the child entity
// however the types change to match the underlying PK attributes 
// (change ParentEntity to int)
 public class ChildId implements Serializable {
        int parentEntity;
        String childName;

        public ChildId() { //... }

        // Add extra constructor & remove setter methods so Id objects are immutable
        public ChildId(int parentEntity, String childName) { //... }


        public int getParentEntity() { //... }
        // make Id objects immutable:
        //  public void setParentEntity(int parentEntity) { //... }
        public String getChildName() { //... }
        //  public void setChildName(String childName) { //... }
}

Tente assim:

@TableGenerator(name = "canonicalKeys", allocationSize = 1, initialValue = 1)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "canonicalKeys")
@Column(name = "CANONICAL_ID", unique = false, nullable = false, insertable = true, updatable = true)
public String getCanonicalId() {
    return canonicalId;
}

Desta forma, em vez de usar uma seqüência que você pode usar uma tabela.

Eu noto que parece que o seu construção de uma chave composta primária como esta exemplo . Enquanto eu estava cutucando um problema semelhante no meu próprio banco de dados Eu me perguntava se talvez você poderia chamar o sql diretamente como:

select nextval ('hibernate_sequence')

Suponho que seria batota embora; -)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top