Как аннотировать поле автоинкремента MYSQL с помощью аннотаций JPA

106

Сразу проблема заключается в сохранении объекта Operator в MySQL DB. Перед сохранением я пытаюсь выбрать из этой таблицы, и она работает, как и подключение к db.

Вот мой объект Operator:

@Entity
public class Operator{

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;


   private Integer active;

   //Getters and setters...
}

Для сохранения я использую JPA EntityManager«s persistметод.

Вот какой журнал:

Hibernate: insert into Operator (active, password, username, id) values (?, ?, ?, ?)
com.mysql.jdbc.JDBC4PreparedStatement@15724a0: insert into Operator (active,password, username, id) values (0, 'pass', 'user', ** NOT SPECIFIED **)

На мой взгляд, проблема заключается в настройке с автоматическим приращением, но я не могу понять, где.

Пробовал некоторые трюки, которые я видел здесь: Hibernate не уважает поле первичного ключа MySQL auto_increment Но ничего из этого не сработало

Если потребуются другие файлы конфигурации, я их предоставлю.

DDL:

CREATE TABLE `operator` ( 
`id` INT(10) NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR(40) NOT NULL,
`last_name` VARCHAR(40) NOT NULL,
`username` VARCHAR(50) NOT NULL,
`password` VARCHAR(50) NOT NULL,
`active` INT(1) NOT NULL,
PRIMARY KEY (`id`)
)
тривунм
источник
Какую версию Hibernate вы используете?
Стивен Бенитес

Ответы:

150

Чтобы использовать AUTO_INCREMENTстолбец MySQL , вы должны использовать IDENTITYстратегию:

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;

Вот что вы получите при использовании AUTOс MySQL:

@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

Что на самом деле эквивалентно

@Id @GeneratedValue
private Long id;

Другими словами, ваше отображение должно работать. Но Hibernate должен опускать idстолбец в операторе вставки SQL, а это не так. Где-то должно быть какое-то несоответствие.

Вы указали диалект MySQL в конфигурации Hibernate (возможно, MySQL5InnoDBDialectилиMySQL5Dialect зависимости от используемого движка)?

Кроме того, кто создал таблицу? Можете показать соответствующий DDL?

Продолжение: я не могу воспроизвести вашу проблему. Используя код вашей сущности и вашего DDL, Hibernate генерирует следующий (ожидаемый) SQL с MySQL:

insert 
into
    Operator
    (active, password, username) 
values
    (?, ?, ?)

Обратите внимание, что idстолбец отсутствует в приведенном выше заявлении, как и ожидалось.

Подводя итог, ваш код, определение таблицы и диалект правильные и согласованные, он должен работать. Если это не для вас, возможно, что-то не синхронизировано (выполните чистую сборку, дважды проверьте каталог сборки и т. Д.) Или что-то еще не так (проверьте журналы на наличие чего-либо подозрительного).

Что касается диалекта, единственная разница между MySQL5Dialectили MySQL5InnoDBDialectзаключается в том, что последний добавляет ENGINE=InnoDBк таблице объекты при генерации DDL. Использование того или другого не меняет сгенерированный SQL.

Паскаль Тивент
источник
Паскаль, вы правы, но что-то в моих файлах конфигурации не так. Может быть, есть какие-то другие предложения, теперь, когда я добавил новую информацию и файлы конфигурации?
trivunm
9
@Pascal - Я обнаружил, что мне нужен @GeneratedValue (strategy = GenerationType.IDENTITY), чтобы AUTO_INCREMENT работал правильно при использовании JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7. bit.ly/tdNyOJ
Джошуа Дэвис,
4
Обратите внимание, что это верно для MySQL . С PostgreSQL вы не получите, @GeneratedValue(strategy=GenerationType.IDENTITY)когда пишете @GeneratedValue(strategy=GenerationType.AUTO)и @GeneratedValue. Так что будьте осторожны и постарайтесь быть многословным.
sajjadG
Примечание: в более поздних версиях Hibernate и / или MySQL / MariaDB GenerationType.AUTO по умолчанию будет GenerationType.TABLE. Что при обновлении может привести к неприятным проблемам с рассинхронизацией последовательностей.
jwenting
не забудьте воссоздать таблицу: spring.jpa.hibernate.ddl-auto = create. С обновлением не получится
Glasnhost
38

Используя MySQL, у меня работал только этот подход:

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;

Другие 2 подхода, заявленные Паскалем в его ответе, не работали для меня.

Jelle
источник
Да, я упомянул об этом в своем вопросе / ответе. stackoverflow.com/questions/39675714/…
Ян Хонски,
Спасибо, у меня работает, использую JPAс spring-boot и MySQL.
Усама Аль-Банна
12

Для тех, кто читает это и использует EclipseLink для JPA 2.0, вот две аннотации, которые мне пришлось использовать, чтобы заставить JPA сохранять данные, где «MySequenceGenerator» - любое имя, которое вы хотите дать генератору, «myschema» - это имя схема в вашей базе данных, которая содержит объект последовательности, а «mysequence» - это имя объекта последовательности в базе данных.

@GeneratedValue(strategy= GenerationType.SEQUENCE, generator="MySequenceGenerator")
@SequenceGenerator(allocationSize=1, schema="myschema",  name="MySequenceGenerator", sequenceName = "mysequence")

Для тех, кто использует EclipseLink (и, возможно, других поставщиков JPA), ВАЖНО, чтобы вы установили атрибут allocationSize в соответствии со значением INCREMENT, определенным для вашей последовательности в базе данных. Если вы этого не сделаете, вы получите типичную ошибку устойчивости и потратите много времени, пытаясь ее отследить, как это сделал я. Вот справочная страница, которая помогла мне преодолеть эту проблему:

http://wiki.eclipse.org/EclipseLink/Examples/JPA/PrimaryKey#Using_Sequence_Objects

Кроме того, чтобы дать контекст, вот что мы используем:

Java 7 Glassfish 3.1 PostgreSQL 9.1 PrimeFaces 3.2 / JSF 2.1

Кроме того, ради лени я построил это в Netbeans с помощью мастеров для генерации сущностей из БД, контроллеров из сущностей и JSF из сущностей, а мастера (очевидно) не знают, как работать со столбцами идентификаторов на основе последовательностей, поэтому вам придется вручную добавить эти аннотации.

Макс Потрясающий
источник
6

Пожалуйста, убедитесь, что тип данных id - Long вместо String, если это будет строка, тогда аннотация @GeneratedValue не будет работать, и sql, генерируемый для

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private String id;

create table VMS_AUDIT_RECORDS (id **varchar(255)** not null auto_increment primary key (id))

это должно быть

create table VMS_AUDIT_RECORDS (id **bigint** not null auto_increment primary key (id))
АБХАЙ ДЖОХРИ
источник
6

Если вы используете Mysql с Hibernate v3, его можно использовать, GenerationType.AUTOпотому что внутри он будет использоватьGenerationType.IDENTITY , что является наиболее оптимальным для MySQL.

Однако в Hibernate v5 это изменилось. GenerationType.AUTOбудет использовать GenerationType.TABLEкоторый генерирует много запросов для вставки.

Вы можете избежать этого, используя GenerationType.IDENTITY(если MySQL - единственная база данных, которую вы используете) или с этими обозначениями (если у вас несколько баз данных):

@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
dmarquina
источник
да, хитрая причина для некоторых неприятных ошибок регрессии при обновлении вашего приложения Spring, которое внутри также обновляет Hibernate.
jwenting
1

Я пробовал все, но все равно не смог этого сделать, я использую mysql, jpa с hibernate, я решил свою проблему, присвоив значение id 0 в конструкторе. Ниже приведен мой код объявления id.

@Id
@Column(name="id",updatable=false,nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
М. Васим Уллах Хан
источник
1

Поскольку вы определили идентификатор в типе int при создании базы данных, вы также должны использовать тот же тип данных в классе модели. И поскольку вы определили идентификатор для автоматического увеличения в базе данных, вы должны упомянуть его в классе модели, передав значение GenerationType.AUTO в атрибут «стратегия» в аннотации @GeneratedValue. Тогда код станет таким, как показано ниже.

@Entity
public class Operator{

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private int id;

  private String username;

  private String password;

  private Integer active;

  //Getters and setters...
}
Анджали Павитра
источник
1

так же, как ответил паскаль, просто если вам по какой-то причине нужно использовать .AUTO, вам просто нужно добавить в свойства вашего приложения:

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto = update
Хорхе
источник
0

Можете ли вы проверить, подключились ли вы к правильной базе данных. поскольку я столкнулся с той же проблемой, но, наконец, обнаружил, что подключился к другой базе данных.

identity поддерживает столбцы идентичности в DB2, MySQL, MS SQL Server, Sybase и HypersonicSQL. Возвращаемый идентификатор имеет тип long, short или int.

Дополнительная информация: http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/mapping.html#mapping-declaration-id

Мохан Редди
источник