Java – JPA – Генераторы – @SequenceGenerator
Я изучаю JPA и @SequenceGenerator
annotations @SequenceGenerator
.
Насколько я понимаю, он автоматически присваивает значение числовым идентификационным полям / свойствам объекта.
Q1. Создает ли этот генератор последовательности использование возможности создания числовой величины базы данных или генерирует ее собственный?
- Когда JPA устанавливает @GeneratedValue @Id
- Hibernate, @SequenceGenerator и allocSize
- Java JPA Class для MATLAB
- Указывает ли спецификация JPA ссылки на столбцы не первичного ключа?
- Почему Hibernate Open Session in View считается плохой практикой?
Q2. Если JPA использует функцию автоматического увеличения базы данных, то будет ли она работать с хранилищами данных, у которых нет функции автоматического увеличения?
Q3. Если JPA генерирует числовое значение самостоятельно, то как реализация JPA знает, какое значение будет генерироваться следующим? Проводит ли он сначала с базой данных, чтобы узнать, какое значение было сохранено последним, чтобы сгенерировать значение (последнее + 1)?
Q4. Кроме того, пролить свет на sequenceName
и @SequenceGenerator
свойства @SequenceGenerator
annotations.
- Spring. Возможно ли использовать несколько менеджеров транзакций в одном приложении?
- Нарушение спящего режима с помощью orphanRemoval
- Поддержка JPA для Java 8 новых API даты и времени
- Спящий режим: создание таблиц Mysql InnoDB вместо MyISAM
- Получение соединения с базой данных в чистой настройке JPA
- PersistenceContext EntityManager инъекции NullPointerException
- Hibernate: индивидуальная ленивая загрузка, необязательно = false
- Как использовать enums с JPA
sequenceName
– это имя последовательности в БД. Вот как вы указываете последовательность, которая уже существует в БД. Если вы идете по этому маршруту, вам нужно указать allocationSize
который должен быть того же значения, что и последовательность DB, в качестве «автоматического приращения».
Применение:
@GeneratedValue(generator="my_seq") @SequenceGenerator(name="my_seq",sequenceName="MY_SEQ", allocationSize=1)
Если вы хотите, вы можете позволить ему создать последовательность для вас. Но для этого вы должны использовать SchemaGeneration, чтобы создать его. Для этого используйте:
@GeneratedValue(strategy=GenerationType.SEQUENCE)
Кроме того, вы можете использовать автоматическое поколение, которое будет использовать таблицу для генерации идентификаторов. Вы также должны использовать SchemaGeneration в какой-то момент при использовании этой функции, поэтому можно создать таблицу генераторов. Для этого используйте:
@GeneratedValue(strategy=GenerationType.AUTO)
Я использую это, и он работает правильно
@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; }
Хотя этот вопрос очень старый, и я наткнулся на него по своим собственным проблемам с последовательностями 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 так, чтобы они были синхронизированы, но firebase database JPA вызывает каждый последующий порядковый номер.
Если вы не хотите каждый раз обращаться к базе данных, используйте страtagsю 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: невозможно кэшировать значения последовательности для последовательности «RECORD_ID_SEQ». У вашего приложения нет разрешения на выполнение команды ALTER SEQUENCE. Убедитесь, что у него есть соответствующее разрешение для запуска команды ALTER SEQUENCE.
Поскольку JPA не может изменить последовательность, JPA каждый раз обращается к базе данных, чтобы получить следующий порядковый номер независимо от значения @ SequenceGenerator.allocationSize. Это может быть нежелательным следствием, о котором нам нужно знать.
Чтобы JPA не запускала эту команду, установите это значение – в файле persistence.xml. Это гарантирует, что JPA не будет пытаться выполнить команду ALTER SEQUENCE. Он пишет другое предупреждение, хотя –
00000094 Runtime W CWWJP9991W: openjpa.Runtime: Warn: свойство “openjpa.jdbc.DBDictionary = disableAlterSeqenceIncrementBy” установлено в true. Это означает, что оператор SQL ALTER SEQUENCE … INCREMENT BY SQL не будет выполнен для последовательности «RECORD_ID_SEQ». OpenJPA выполняет эту команду, чтобы гарантировать, что значение INCREMENT BY последовательности, определенное в базе данных, соответствует распределению, которое определено в последовательности сущности. Когда этот оператор SQL отключен, пользователь должен убедиться, что определение последовательности сущности соответствует последовательности, определенной в базе данных.
Как отмечено в предупреждении, важно здесь: мы должны убедиться, что @ SequenceGenerator.allocationSize и INCREMENT BY в определении последовательности базы данных синхронизированы, включая значение по умолчанию @SequenceGenerator (allocSize), которое равно 50. В противном случае это вызовет ошибки.
У меня есть схема 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; } }