2010-04-07 3 views
33

Я изучаю JPA и путаюсь в аннотации @SequenceGenerator.Java - JPA - Генераторы - @SequenceGenerator

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

Q1. Создает ли этот генератор последовательности использование возможности генерации числового значения базы данных или генерирует номер на своем собственном?

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

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


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

ответ

47

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) 
+3

Поставщик JPA (например, Hibernate) будет использовать значение последовательности в качестве базы и * mutiply * его с allocSize, чтобы получить фактический идентификатор, который он будет вставлять. Поэтому, если следующее значение seq равно 11, а allocSize равно 20, следующий сгенерированный идентификатор будет 220. Обычно вы просто хотите, чтобы ваши идентификаторы соответствовали точно значению последовательности, поэтому установите allocSize = INCREMENT BY последовательности. См. Также http://stackoverflow.com/questions/5346147/hibernate-oracle-sequence-produces-large-gap –

+0

Это не работает для столбцов без id. –

2

У меня есть схема MySQL с автогенными значениями. Я использую тег 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; } 
} 
9

Я использую это и работает прямо

@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 (allocationSize) из GenerationType.ПОСЛЕДОВАТЕЛЬНОСТЬ и Инкримента в определении последовательности базы данных

Убедитесь @SequenceGenerator (allocationSize) устанавливается на тот же величину, Инкримента в определении последовательности базы данных, чтобы избежать проблем. Для примера. если мы определим последовательность в базе данных с 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 объекта сохраняются в БД и значение идентификатора присваиваются возвращенным объект, поэтому мы не должны делать em.merge или ет .flush. (Это может быть поставщик JPA specific..Not уверен)

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

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

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 Продолжительность W CWWJP9991W: openjpa.Runtime: Предупреждение: The свойство «openjpa.jdbc.DBDictionary = disableAlterSeqenceIncrementBy»является значения ИСТИНЫ. Это означает, что„ALTER SEQUENCE ... INCREMENT BY“SQL заявления не будет выполняться в последовательности„RECORD_ID_SEQ“. OpenJPA выполняет эту команду, чтобы убедиться, что увеличивают последовательности пути значения определенно в базе данных соответствует значению allocationSize, который определен в последовательности хозяйствующего субъекта. при этом SQL заявлении отключенного, это ответственности пользователя, чтобы убедиться, что определение последовательности в лице соответствует последовательности, определенной в базе данных.

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

Смежные вопросы