Как аннотировать поле автоинкремента MYSQL с аннотациями JPA
Прямо к точке, проблема заключается в том, чтобы сохранить объект 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 (?, ?, ?, ?)
[email protected]: 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`)
)
Ответы
Ответ 1
Чтобы использовать столбец MySQL AUTO_INCREMENT
, вы должны использовать стратегию 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 insert, и это не так. Там должно быть какое-то несоответствие.
Вы указали диалоги MySQL в своей конфигурации Hibernate (возможно, MySQL5InnoDBDialect
или MySQL5Dialect
в зависимости от используемого вами движка)?
Кроме того, кто создал таблицу? Вы можете показать соответствующий DDL?
Последующее наблюдение: Я не могу воспроизвести вашу проблему. Используя код вашего объекта и ваш DDL, Hibernate генерирует следующий (ожидаемый) SQL с MySQL:
insert
into
Operator
(active, password, username)
values
(?, ?, ?)
Обратите внимание, что столбец id
отсутствует в приведенном выше выражении, как и ожидалось.
Подводя итог, ваш код, определение таблицы и диалект являются правильными и последовательными, они должны работать. Если это не для вас, возможно, что-то не синхронизировано (выполните чистую сборку, дважды проверьте каталог сборки и т.д.) Или что-то еще не так (проверьте журналы на что-нибудь подозрительное).
Что касается диалекта, единственное различие между MySQL5Dialect
или MySQL5InnoDBDialect
заключается в том, что позднее добавляет ENGINE=InnoDB
к объектам таблицы при генерации DDL. Использование одного или другого не изменяет сгенерированный SQL.
Ответ 2
Используя MySQL, для меня работал только этот подход:
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
Другие 2 подхода, заявленные Паскалем в его ответе, не работали для меня.
Ответ 3
Для тех, кто читает это, кто использует 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), CRITICAL устанавливает атрибут allocSize в соответствие с значением 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 с помощью мастеров для создания Entities из DB, контроллеров от Entities и JSF от Entities, а мастера (очевидно) не знают, как обращаться с идентификатором на основе последовательности столбцы, поэтому вам придется вручную добавлять эти аннотации.
Ответ 4
Пожалуйста, убедитесь, что тип данных 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))
Ответ 5
Я перепробовал все, но все же я не смог этого сделать, я использую mysql, jpa с hibernate, я решил свою проблему, присвоив значение id 0 в конструкторе. Ниже приведен мой код объявления идентификатора.
@Id
@Column(name="id",updatable=false,nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Ответ 6
Можете ли вы проверить, подключены ли вы к правильной базе данных. как я столкнулся с той же проблемой, но в конце концов я обнаружил, что я подключен к другой базе данных.
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
Ответ 7
Поскольку вы определяете идентификатор в типе 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...
}
Ответ 8
Если вы используете 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")