Pregunta

¿Es posible en las extensiones simples de JPA o JPA + Hibernar declarar una clave compuesta, donde un elemento de la clave compuesta es una secuencia?

Esta es mi clase compuesta:

@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;
    }

    //...
}

Ya proporcioné los valores para application , entidad , nativeId y nativeKey . Quiero construir una entidad como la de abajo:

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

Y cuando llamo a em.persist (i1 ), quiero que se genere canonicalId y se inserte la integración.

¿Es esto posible? Si es así, ¿cuál es la forma más sencilla? (Prefiero no usar las claves proporcionadas por la aplicación o el SQL nativo).

¿Fue útil?

Solución

Creo que esto no es posible con JPA simple.

Otros consejos

El uso de @GeneratedValue para PKs compuestas no se especifica con la especificación JPA 2.

De la especificación JPA:

  

11.1.17 GeneratedValue Annotation

     

La anotación GeneratedValue proporciona la especificación de   Generación de estrategias para los valores de las claves primarias. los   La anotación GeneratedValue se puede aplicar a una propiedad de clave primaria o   campo de una entidad o superclase asignada junto con el Id.   anotación. [97] El uso de la anotación GeneratedValue es solamente   Se requiere que sea compatible con claves primarias simples. Uso de la   La anotación GeneratedValue no es compatible con las claves primarias derivadas.

Tenga en cuenta que, en un escenario diferente, puede tener una entidad principal con un PK simple (@Id) que usa @GeneratedValue, y luego tener una entidad secundaria que tiene un PK compuesto que incluye la identificación generada del padre, más otra columna.

  • Otorgue al niño una relación @ManyToOne con la entidad principal, para que herede el ID generado en una columna FK.
  • Luego, proporcione al niño una PK compuesta, a través de @IdClass especificada contra la entidad, más dos columnas @Id dentro de la entidad.
@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) { //... }
}

Prueba esto:

@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;
}

De esta manera, en lugar de usar una secuencia, puedes usar una tabla.

Me doy cuenta de que parece que estás construyendo una clave principal compuesta como esta example . Mientras buscaba un problema similar en mi propia base de datos, me preguntaba si tal vez podrías llamar al sql directamente como:

seleccione nextval ('hibernate_sequence')

Supongo que eso sería hacer trampa ;-)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top