MYSQL自動インクリメントフィールドにJPAアノテーションを付ける方法


105

端的に言うと、問題はオブジェクトオペレーターを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 EntityManagerpersistメソッドを使用します。

ここにいくつかのログがあります:

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

MySQL AUTO_INCREMENT列を使用するには、IDENTITY戦略を使用する必要があります。

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

AUTOMySQLで使用すると、次のようになります。

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

これは実際には

@Id @GeneratedValue
private Long id;

つまり、マッピングは機能するはずです。しかし、HibernateはidSQL挿入ステートメントで列を省略すべきであり、そうではありません。どこかにある種のミスマッチがあるに違いない。

Hibernate構成でMySQL方言を指定しましたか(おそらく、MySQL5InnoDBDialectまたはMySQL5Dialect使用しているエンジンに依存します)?

また、誰がテーブルを作成しましたか?対応するDDLを表示できますか?

フォローアップ:問題を再現できません。コード使用して、あなたのエンティティとあなたの DDLを、HibernateはMySQLで、次の(期待)SQLを生成します。

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

id予想通り、上記のステートメントには列がありません。

要約すると、コード、テーブル定義、および方言は正しく、首尾一貫しており、機能するはずです。うまくいかない場合は、何かが同期していない(クリーンビルドを実行する、ビルドディレクトリを再確認するなど)か、何かが間違っている(疑わしいものがないかログを確認してください)。

方言に関しては、または の唯一の違いは、DDLの生成時に後者がテーブルオブジェクトに追加することです。どちらを使用しても、生成されたSQLは変更されません。MySQL5DialectMySQL5InnoDBDialectENGINE=InnoDB


パスカル、あなたはそれについて正しいですが、私の設定ファイルの何かはちょうど正しくありません。新しい情報と構成ファイルを配置したので、他の提案はおそらくありますか?
trivunm 2010年

9
@Pascal-JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7. bit.ly/tdNyOJ
Joshua Davis

4
これはMySQLにも当てはまります。ではPostgreSQLのあなたが得ることはありません@GeneratedValue(strategy=GenerationType.IDENTITY)あなたが書いたとき@GeneratedValue(strategy=GenerationType.AUTO)@GeneratedValue。したがって、注意して、冗長になるようにしてください。
sajjadG 2013年

注: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

おかげで、私にとってはうまくいきます。私はとを使用JPAspring-boot ていMySQLます。
Osama Al-Banna

12

JPA 2.0にEclipseLinkを使用しているこれを読んでいる人のために、JPAにデータを永続化させるために使用しなければならなかった2つの注釈を示します。「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

また、怠惰のために、DBからエンティティを生成するウィザード、エンティティからコントローラを生成するウィザード、およびエンティティからJSFを生成するウィザードを使用してこれをNetbeansに構築しました。ウィザードは(明らかに)シーケンスベースのID列の処理方法を認識していません。これらの注釈を手動で追加する必要があります。


6

MysqlをHibernate v3で使用している場合GenerationType.AUTO、内部でが使用されるためGenerationType.IDENTITY、使用しても問題ありません。これはMySQLに最適です。

ただし、Hibernate v5では変更されています。挿入のために多くのクエリを生成するをGenerationType.AUTO使用しますGenerationType.TABLE

GenerationType.IDENTITYMySQLが使用している唯一のデータベースである場合)またはこれらの表記(複数のデータベースがある場合)を使用することを回避できます。

@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")

はい、Springアプリケーションをアップグレードするときに厄介な回帰エラーが発生するトリッキーな原因です。
jwenting

5

idデータ型が文字列ではなくLongであることを確認してください。文字列になる場合、@ 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))

1

私はあらゆることを試しましたが、それでもそれを行うことができませんでした.mysql、jpaをhibernateで使用しています。コンストラクターでid 0の値を割り当てることで問題を解決しました以下は私のid宣言コードです

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

1

データベースの作成時にint型でidを定義したので、モデルクラスでも同じデータ型を使用する必要があります。また、データベースで自動インクリメントするIDを定義したので、@ GeneratedValueアノテーション内の属性「strategy」に値「GenerationType.AUTO」を渡すことにより、モデルクラスでそれを言及する必要があります。するとコードは以下のようになります。

@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

pascalと同じですが、何らかの理由で.AUTOを使用する必要がある場合は、アプリケーションのプロパティに追加するだけです。

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto = update

0

正しいデータベースに接続したかどうかを確認できますか。同じ問題に直面していましたが、最終的に別のデータベースに接続していることがわかりました。

ID は、DB2、MySQL、MS SQL Server、Sybase、およびHypersonicSQLのID列をサポートしています。返される識別子は、long、short、またはint型です。

詳細情報:http : //docs.jboss.org/hibernate/orm/3.5/reference/en/html/mapping.html#mapping-declaration-id


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.