Java - JPA - Генераторы - @SequenceGenerator - PullRequest
40 голосов
/ 07 апреля 2010

Я изучаю JPA и у меня путаница в аннотации @SequenceGenerator.

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

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

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

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


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

Ответы [ 4 ]

56 голосов
/ 07 апреля 2010

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)
12 голосов
/ 06 августа 2013

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

@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;
}
7 голосов
/ 16 марта 2017

Хотя этот вопрос очень старый, и я наткнулся на него из-за собственных проблем с последовательностями 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. Если значение базы данных больше, чем размер размещения, вы увидите скачки значений 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 Runtime 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. Это означает, что SQL «ALTER SEQUENCE ... INCREMENT BY» Оператор не будет выполнен для последовательности "RECORD_ID_SEQ". OpenJPA выполняет эту команду, чтобы гарантировать, что значение INCREMENT BY последовательности определенный в базе данных, соответствует allocSize, который определен в последовательность объекта. С этим оператором SQL отключен, это ответственность пользователя за обеспечение последовательности объектаопределение соответствует последовательности, определенной в базе данных.

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

3 голосов
/ 26 марта 2013

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

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; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...