Автор оригинала: Vlad Mihalcea.
Как объяснялось ранее, генератор идентификаторов ТАБЛИЦ не масштабируется , поэтому вам следует избегать идентификаторов. Однако некоторым корпоративным приложениям может потребоваться запуск как на MySQL (который не поддерживает последовательности баз данных), так и на Oracle, PostgreSQL и SQL Server 2012.
В этой статье будет объяснено, как легко вы можете достичь этой цели, используя переопределение сопоставления JPA.
Последовательности баз данных являются лучшим выбором генератора идентификаторов при использовании JPA и Hibernate. Это связано с тем, что, в отличие от ИДЕНТИФИКАТОРА
генератора, вы можете воспользоваться пакетными обновлениями JDBC . Поэтому вы всегда должны использовать последовательность баз данных, если базовая база данных поддерживает эту функцию.
@Entity(name = "Post") @Table(name = "post") public class Post { @Id @GeneratedValue( generator = "sequence", strategy = GenerationType.SEQUENCE ) @SequenceGenerator( name = "sequence", allocationSize = 10 ) private Long id; private String title; //Getters and setters omitted for brevity sake }
При сохранении 5 Post
сущностей в PostgreSQL:
doInJPA(entityManager -> { for (int i = 0; i < 5; i++) { Post post = new Post(); post.setTitle( String.format("Post nr %d", i + 1) ); entityManager.persist(post); } });
Hibernate генерирует следующие инструкции SQL:
SELECT nextval ('hibernate_sequence') SELECT nextval ('hibernate_sequence') INSERT INTO post (title, id) VALUES ('Post nr 1', 1) INSERT INTO post (title, id) VALUES ('Post nr 2', 2) INSERT INTO post (title, id) VALUES ('Post nr 3', 3) INSERT INTO post (title, id) VALUES ('Post nr 4', 4) INSERT INTO post (title, id) VALUES ('Post nr 5', 5)
Как вы можете видеть, существует только 2 вызова последовательности, которые определяют минимальную и максимальную границы объединенного оптимизатора .
Для MySQL, поскольку мы не хотим использовать генератор TABLE
, мы обязаны использовать стратегию IDENTITY
identifier. Однако мы хотим повторно использовать предыдущее сопоставление сущностей, поэтому все, что нам нужно,-это предоставить XML-сопоставление JPA, которое переопределяет сопоставление аннотаций на основе Java:
com.vladmihalcea.book.hpjp.hibernate.identifier.global
Все это возможно, потому что спецификация JPA определяет следующее поведение:
Метаданные XML могут использоваться в качестве альтернативы этим аннотациям, а также для переопределения или дополнения аннотации
— Спецификация JPA 2.1, 11.1 Аннотации для объектно-реляционного отображения
Теперь, поскольку я загружаю JPA без persistence.xml файл , мой PersistenceUnitInfo
выглядит так:
PersistenceUnitInfoImpl persistenceUnitInfo = new PersistenceUnitInfoImpl( name, entityClassNames(), properties() ); String[] resources = resources(); if (resources != null) { persistenceUnitInfo .getMappingFileNames() .addAll(Arrays.asList(resources)); }
Итак, для MySQL сопоставление на основе Java выполняется следующим образом:
@Override protected Class>[] entities() { return new Class>[] { Post.class, }; } @Override protected String[] resources() { return new String[] { "mappings/identifier/global/mysql-orm.xml" }; }
Итак, когда я запускаю предыдущий тестовый случай на MySQL, Hibernate генерирует следующие инструкции SQL:
INSERT INTO post (title) VALUES ('Post nr 1') INSERT INTO post (title) VALUES ('Post nr 2') INSERT INTO post (title) VALUES ('Post nr 3') INSERT INTO post (title) VALUES ('Post nr 4') INSERT INTO post (title) VALUES ('Post nr 5')
Как вы можете видеть, сопоставление XML переопределило сопоставление аннотаций только для атрибута идентификатора. Это здорово, так как мы можем повторно использовать все, что мы определили в аннотациях Java, все еще решая проблему переносимости идентификаторов базы данных.
Скорее всего, вы собираетесь использовать persistence.xml
в вашем корпоративном приложении, поэтому конфигурация выглядит следующим образом:
org.hibernate.jpa.HibernatePersistenceProvider mappings/identifier/global/mysql-orm.xml com.vladmihalcea.book.hpjp.hibernate.identifier.global.Post
Вы даже можете использовать файлы сопоставления, расположенные за пределами файла JAR так что среда MySQL просто предоставляет соответствующие orm.xml
файл конфигурации в указанном внешнем каталоге конфигурации.
Вот и все!
Тип поколения. AUTO
не является хорошим выбором для MySQL, так как из режима гибернации 5 он возвращается к ТАБЛИЦЕ
генератору, что плохо сказывается на производительности.
Нет необходимости использовать генератор ТАБЛИЦ
идентификаторов. Если переносимость является вашей основной заботой, вы можете просто использовать ПОСЛЕДОВАТЕЛЬНОСТЬ
по умолчанию и переопределить это стратегией IDENTITY
для MySQL. Просто убедитесь, что среда MySQL поставляется с orm.xml
файл конфигурации, который переопределяет сопоставление ПОСЛЕДОВАТЕЛЬНОСТИ
идентификаторов.