Як коментувати поле для автоматичного збільшення MYSQL за допомогою JPA-анотацій


106

Безпосередньо проблема полягає в збереженні оператора об'єкта в MySQL БД. Перед збереженням я намагаюся вибрати з цієї таблиці, і вона працює, тому є з'єднання з db.

Ось мій об’єкт Оператора:

@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;

Що ви отримаєте при використанні AUTOMySQL:

@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 (стратегія = 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 підходи, які Паскаль заявив у своїй відповіді, не працювали для мене.


Так, я вирішив це у своєму питанні / відповіді. stackoverflow.com/questions/39675714 / ...
Ян Khonski

Дякую, це працює для мене, я використовую 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), КРИТИЧНО встановити атрибут attribute attribute для того, щоб він відповідав значенню 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 з майстрами для генерування об'єктів з DB, Controllers з Entities та JSF з Entities, і майстри (очевидно) не знають, як поводитись із стовпцями на основі послідовностей ідентифікаторів, тож вам доведеться вручну додавати ці примітки.


6

Переконайтесь, що тип даних id довгий замість 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")

так, хитра причина для неприємних помилок регресії під час оновлення програми Spring, яка під капотом також оновлює сплячку.
jwenting

1

Я спробував кожне, але все-таки мені не вдалося це зробити, я використовую mysql, jpa зі сплячим режимом, я вирішив свою проблему, призначивши значення конструктора id 0 у конструкторі. Далі йде мій код декларації id

@Id
@Column(name="id",updatable=false,nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

1

Оскільки ви визначаєте тип id intt при створенні бази даних, вам потрібно використовувати той самий тип даних і в класі моделі. І як ви визначили ідентифікатор для автоматичного збільшення в базі даних, ви повинні згадати його в модельному класі, передаючи значення "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

чи можете ви перевірити, чи підключено ви до правильної бази даних. як я зіткнувся з тією ж проблемою, але нарешті я виявив, що я підключений до іншої бази даних.

ідентичність підтримує стовпці ідентичності в DB2, MySQL, MS SQL Server, Sybase та HypersonicSQL. Повертається ідентифікатор типу довгий, короткий або int.

Детальніше: http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/mapping.html#mapping-declaration-id


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.