JPA составной ключ + последовательность - PullRequest
16 голосов
/ 28 октября 2008

Возможно ли в простых расширениях JPA или JPA + Hibernate объявить составной ключ, где элемент составного ключа является последовательностью?

Это мой составной класс:

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

    //...
}

Я уже предоставляю значения для application, entity, nativeId и nativeKey. Я хочу построить сущность, подобную приведенной ниже:

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

И когда я звоню em.persist(i1), я хочу, чтобы генерировался canonicalId и вставлялась интеграция.

Возможно ли это? Если так, то каков простой способ? (Я предпочитаю не использовать предоставленные приложением ключи или собственный sql).

Ответы [ 4 ]

3 голосов
/ 24 февраля 2009

Я считаю, что это невозможно с простым JPA.

2 голосов
/ 15 октября 2012

Использование @GeneratedValue для составных ПК не указано в спецификации JPA 2.

Из спецификации JPA:

11.1.17 Генерируемая аннотация значения

Аннотация GeneratedValue содержит спецификацию стратегии генерации значений первичных ключей. Аннотация GeneratedValue может применяться к свойству первичного ключа или поле сущности или сопоставленного суперкласса в сочетании с идентификатором аннотаций. [97] Использование аннотации GeneratedValue только требуется для поддержки простых первичных ключей. Использование Аннотация GeneratedValue не поддерживается для производных первичных ключей.

Обратите внимание, что в другом сценарии вы можете иметь родительский объект с простым PK (@Id), который использует @GeneratedValue, а затем иметь дочерний объект, который имеет составной PK, который включает в себя созданный Id из родительского элемента плюс другой столбец.

  • Дайте ребенку отношение @ManyToOne к родительскому объекту, чтобы он наследовал созданный идентификатор в столбце FK.
  • Затем передайте дочернему элементу составной PK через @IdClass, указанный для сущности, плюс два столбца @Id внутри сущности.
@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) { //... }
}
1 голос
/ 30 марта 2009

Я замечаю, что создается ваш составной первичный ключ, подобный этому пример . Пока я пытался найти аналогичную проблему в моей собственной базе данных, я подумал, может быть, вы могли бы вызвать sql напрямую, например:

select nextval ('hibernate_sequence')

Полагаю, это будет обманом; -)

1 голос
/ 28 октября 2008

Попробуй так:

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

Таким образом, вместо использования последовательности вы можете использовать таблицу.

...