Подтвердить что ты не робот

Java - JPA - Генераторы - @SequenceGenerator

Я изучаю JPA и путаюсь в аннотации @SequenceGenerator.

Насколько я понимаю, он автоматически присваивает значение числовым идентификационным полям/свойствам объекта.

Q1. Использует ли этот генератор последовательности базу данных, увеличивающую числовое значение, генерирующую способность или генерирует номер на ней?

Q2. Если JPA использует функцию автоматического увеличения базы данных, то будет ли она работать с хранилищами данных, у которых нет функции автоматического увеличения?

Q3. Если JPA генерирует числовое значение самостоятельно, то как реализация JPA знает, какое значение будет генерироваться дальше? Проконсультируется ли он сначала с базой данных, чтобы узнать, какое значение было сохранено последним для генерации значения (last + 1)?


Q4. Просьба также пролить свет на sequenceName и allocationSize свойства аннотации @SequenceGenerator.
4b9b3361

Ответ 1

sequenceName - это имя последовательности в БД. Вот как вы указываете последовательность, которая уже существует в БД. Если вы пройдете этот маршрут, вам нужно указать allocationSize, который должен быть тем же значением, что и последовательность БД, в качестве "автоматического приращения".

Использование:

@GeneratedValue(generator="my_seq")
@SequenceGenerator(name="my_seq",sequenceName="MY_SEQ", allocationSize=1)

Если вы хотите, вы можете позволить ему создать последовательность для вас. Но для этого вы должны использовать SchemaGeneration, чтобы создать его. Для этого используйте:

@GeneratedValue(strategy=GenerationType.SEQUENCE)

Кроме того, вы можете использовать автоматическое поколение, которое будет использовать таблицу для генерации идентификаторов. Вы также должны использовать SchemaGeneration в какой-то момент при использовании этой функции, поэтому можно создать таблицу генераторов. Для этого используйте:

@GeneratedValue(strategy=GenerationType.AUTO)

Ответ 2

Я использую это, и он работает правильно

@Id
@GeneratedValue(generator = "SEC_ODON", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "SEC_ODON", sequenceName = "SO.SEC_ODON",allocationSize=1)
@Column(name="ID_ODON", unique=true, nullable=false, precision=10, scale=0)
public Long getIdOdon() {
    return this.idOdon;
}

Ответ 3

Несмотря на то, что этот вопрос очень старый, и я наткнулся на него по своим собственным проблемам с последовательностями JPA 2.0 и Oracle.

Хотите поделиться своими исследованиями по некоторым вещам -

Связь между @SequenceGenerator (allocSize) GenerationType.SEQUENCE и INCREMENT BY в определении последовательности данных

Убедитесь, что @SequenceGenerator (allocSize) установлено на то же значение, что и INCREMENT BY, в определении последовательности базы данных, чтобы избежать проблем. Напр. если мы определим последовательность в базе данных с INCREMENT BY значением 20, установите allocationsize в SequenceGenerator также на 20. В этом случае JPA не будет делать вызов в базу данных до тех пор, пока она не достигнет следующей отметки 20, пока она увеличивает каждое значение на 1 внутренне. Это экономит вызовы базы данных для получения следующего порядкового номера каждый раз. Побочным эффектом этого является: - всякий раз, когда приложение перераспределяется или сервер перезапускается между ними, он вызывает базу данных для получения следующей партии, и вы увидите подсказки в значениях последовательности. Также нам нужно убедиться, что определение базы данных и параметр приложения будут синхронизированы, которые могут быть недоступны все время, так как оба они управляются разными группами, и вы можете быстро потерять контроль над ними. Если значение базы данных меньше, чем распределение, вы увидите ошибки ограничения PrimaryKey из-за повторяющихся значений Id. Если значение базы данных выше, чем allocationsize, вы увидите подсказки в значениях Id.

Если для последовательности базы данных INCREMENT BY установлено значение 1 (что обычно используется администраторами баз данных), установите allocSize как 1 так, чтобы они были синхронизированы, но база данных JPA вызывает каждый раз, чтобы получить следующий порядковый номер.

Если вы не хотите каждый раз обращаться к базе данных, используйте стратегию GenerationType.IDENTITY и значение @Id, заданное триггером базы данных. С GenerationType.IDENTITY, как только мы вызываем em.persist, объект сохраняется в БД, а значение для id присваивается возвращенному объекту, поэтому нам не нужно делать em.merge или em.flush. (Это может быть специфический поставщик JPA.. Не уверен)

Еще одна важная вещь -

JPA 2.0 автоматически запускает команду ALTER SEQUENCE, чтобы синхронизировать allocSize и INCREMENT BY в последовательности базы данных. Поскольку в основном мы используем другое имя схемы (имя пользователя приложения), а не фактическую схему, где существует последовательность, и имя пользователя приложения не будет иметь привилегии ALTER SEQUENCE, вы можете увидеть предупреждение ниже в журналах -

000004c1 Время выполнения W CWWJP9991W: openjpa.Runtime: Warn: Unable для кэширования значений последовательности для последовательности "RECORD_ID_SEQ". Ваш приложение не имеет права запускать команду ALTER SEQUENCE. Убедитесь, что у него есть соответствующее разрешение для запуска ALTER SEQUENCE команда.

Поскольку JPA не может изменить последовательность, JPA каждый раз обращается к базе данных, чтобы получить следующий порядковый номер независимо от значения @SequenceGenerator.allocationSize. Это может быть нежелательным следствием, о котором нам нужно знать.

Чтобы JPA не запускала эту команду, установите это значение - в файле persistence.xml. Это гарантирует, что JPA не будет пытаться выполнить команду ALTER SEQUENCE. Он пишет другое предупреждение, хотя -

00000094 Runtime W CWWJP9991W: openjpa.Runtime: Предупреждение: свойство "openjpa.jdbc.DBDictionary = disableAlterSeqenceIncrementBy" является установите значение true. Это означает, что "ALTER SEQUENCE... INCREMENT BY" SQL оператор не будет выполняться для последовательности "RECORD_ID_SEQ". OpenJPA выполняет эту команду, чтобы гарантировать, что значение INCREMENT BY последовательности определенный в базе данных, соответствует распределению, которое определено в последовательность сущностей. Поскольку этот оператор SQL отключен, это ответственность пользователя за то, чтобы последовательность объектов определение соответствует последовательности, определенной в базе данных.

Как отмечено в предупреждении, важно здесь, чтобы убедиться, что @SequenceGenerator.allocationSize и INCREMENT BY в определении последовательности базы данных синхронизированы, включая значение по умолчанию @SequenceGenerator (allocSize), которое равно 50. В противном случае это приведет к ошибки.

Ответ 4

У меня есть схема MySQL с значениями autogen. Я использую тег strategy=GenerationType.IDENTITY и, кажется, отлично работает в MySQL, я думаю, он должен работать и с большинством движков db.

CREATE TABLE user (
    id bigint NOT NULL auto_increment,
    name varchar(64) NOT NULL default '',
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

User.java:

// mark this JavaBean to be JPA scoped class
@Entity
@Table(name="user")
public class User {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;    // primary key (autogen surrogate)

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

    public long getId() { return id; }
    public void setId(long id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name=name; }
}