Как создать и обрабатывать составной первичный ключ в JPA

Я хочу иметь версии из той же записи данных. Другими словами, я хочу продублировать запись с другим номером версии.

id - Version будет первичным ключом.

Как должна выглядеть сущность? Как я могу продублировать его с другой версией?

id Version ColumnA

1   0      Some data
1   1      Some Other data
2   0      Data 2. Entry
2   1      Data

person Kayser    schedule 23.10.2012    source источник
comment
Еще один совет, который я обнаружил при использовании аннотации @IdClass, заключается в том, что аннотация @Column должна входить в поля класса Entity (YourEntity в примере кода RohitJan).   -  person KenSV    schedule 30.11.2017


Ответы (4)


Вы можете создать Embedded class, который содержит ваши два ключа, а затем иметь ссылку на этот класс как EmbeddedId в вашем Entity.

Вам понадобятся @EmbeddedId и @Embeddable аннотации.

@Entity
public class YourEntity {
    @EmbeddedId
    private MyKey myKey;

    @Column(name = "ColumnA")
    private String columnA;

    /** Your getters and setters **/
}
@Embeddable
public class MyKey implements Serializable {

    @Column(name = "Id", nullable = false)
    private int id;

    @Column(name = "Version", nullable = false)
    private int version;

    /** getters and setters **/
}

Другой способ выполнить эту задачу — использовать аннотацию @IdClass и поместить оба ваших id в этот IdClass. Теперь вы можете использовать обычную аннотацию @Id для обоих атрибутов.

@Entity
@IdClass(MyKey.class)
public class YourEntity {
   @Id
   private int id;
   @Id
   private int version;

}

public class MyKey implements Serializable {
   private int id;
   private int version;
}
person Rohit Jain    schedule 23.10.2012
comment
Можно ли использовать @Generatedvalue для идентификаторов с помощью EmbeddedId - person Kayser; 24.10.2012
comment
@Кайзер. Насколько я знаю. Нет. Вы должны явно установить для них значение в своем экземпляре KeyClass, а затем установить этот экземпляр ключевого класса в своей сущности. - person Rohit Jain; 24.10.2012
comment
@Кайзер. @GeneratedValue можно использовать только для генерации значений ключа для первичного ключа, он не может генерировать комбинацию для составных ключей. - person Rohit Jain; 24.10.2012
comment
@Кайзер. См. Section - 11.1.17 GeneratedValue Annotation спецификации JPA 2.0. В нем четко сказано, что @GeneratedValue можно использовать только с простым первичным ключом. - person Rohit Jain; 24.10.2012
comment
@RohitJain только одно: вы на самом деле не можете сделать встроенный класс общедоступным (должен быть в своем собственном файле, чтобы быть общедоступным) - person Lucas; 31.03.2014
comment
+1 Хороший ответ, было бы еще лучше, если бы вы могли дать ссылку на документ, в котором описан этот подход. - person avalancha; 01.08.2014
comment
Только для добавления информации: MyKey класс должен быть статическим для работы с JPA! - person andPat; 11.11.2015
comment
Можно ли сказать JPA (в eclise из нового объекта jpa из таблицы) создать один файл класса вместо двух bean-компонентов, один с данными, а другой с первичным ключом? @RohitJain - person Accollativo; 15.03.2016
comment
Просто добавлю: если у вас есть, например, класс MyEntity таблицы, в которой каждый столбец является первичным ключом, вы можете объявить его @Embeddable и использовать аннотацию @IdClass(value=MyEntity.class) (да, IdClass — это сам класс MyEntity) и аннотировать все первичные ключевые столбцы с @Id. Если вам случится использовать Spring Data JPA, ваш репозиторий должен будет расширить CrudRepository<MyEntity, MyEntity>. - person nonzaprej; 03.04.2017
comment
Извините, @AbdullahKhan - сайт, похоже, удален или недоступен. Оставлю пока там на случай, если он вернется - person Fast Engy; 08.08.2017
comment
@FastEngy К нему по-прежнему можно получить доступ через Wayback Machine: https://web.archive.org/web/20170123035517/http://uaihebert.com/tutorial-jpa-composite-primary-key. Похоже, что эта статья заменена https://web.archive.org/web/20170202203555/http://uaihebert.com/jpa-mini-book-first-steps-and-detailed-concepts/8/ и https://web.archive.org/web/20161014051056/http://uaihebert.com/jpa-mini-book-first-steps-and-detailed-concepts/9/, который также исчез… - person radlan; 05.03.2018
comment
Для «Другого способа выполнить эту задачу...» (для меня) класс MyKey с аннотацией @IdClass(MyKey.class) класс должен был быть static, чтобы работать. - person Dirk Schumacher; 15.12.2019

Класс MyKey должен реализовать Serializable, если вы используете @IdClass

person Swapnil17    schedule 24.09.2015

Ключевой класс:

@Embeddable
@Access (AccessType.FIELD)
public class EntryKey implements Serializable {

    public EntryKey() {
    }

    public EntryKey(final Long id, final Long version) {
        this.id = id;
        this.version = version;
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getVersion() {
        return this.version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public boolean equals(Object other) {
        if (this == other)
            return true;
        if (!(other instanceof EntryKey))
            return false;
        EntryKey castOther = (EntryKey) other;
        return id.equals(castOther.id) && version.equals(castOther.version);
    }

    public int hashCode() {
        final int prime = 31;
        int hash = 17;
        hash = hash * prime + this.id.hashCode();
        hash = hash * prime + this.version.hashCode();
        return hash;
    }

    @Column (name = "ID")
    private Long id;
    @Column (name = "VERSION")
    private Long operatorId;
}

Класс сущности:

@Entity
@Table (name = "YOUR_TABLE_NAME")
public class Entry implements Serializable {

    @EmbeddedId
    public EntryKey getKey() {
        return this.key;
    }

    public void setKey(EntryKey id) {
        this.id = id;
    }

    ...

    private EntryKey key;
    ...
}

Как я могу продублировать его с другой версией?

Вы можете отсоединить объект, полученный от провайдера, изменить ключ записи, а затем сохранить его как новый объект.

person callfarc0de    schedule 23.10.2012
comment
Можно ли определить идентификатор в Entrykey AUTOGENERATED. закажите что-нибудь подобное @GeneratedValue(strategy = GenerationType.IDENTITY) - person Kayser; 23.10.2012
comment
Мне также интересно, как рассчитать хэш для двух длинных первичных ключей. Что касается hash и prime в методе hashCode в классе EntryKey, можете ли вы сказать мне, откуда взялась эта идея? - person Bruce Sun; 26.03.2017

Класс MyKey (@Embeddable) не должен иметь отношений типа @ManyToOne.

person Ranuka    schedule 11.07.2017
comment
Почему нет? Вы смотрели этот пример? - person Buhake Sindi; 29.06.2018