118
105

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

@GeneratedValueを使って主キーを生成する方法

Posted at

JPAにおいて、@GeneratedValueを使って主キーにユニークな値を自動で生成し、@Idを持つフィルドに適用できます。この主キーの値を生成するために、以下4種類の方法があります。
GenerationType.IDENTITY
GenerationType.SEQUENCE
GenerationType.TABLE
GenerationType.AUTO
DBMS毎にそれらの違いを検証して見ました。

検証環境

  • Spring Boot 1.4.3.RELEASE
  • PostgreSQL 9.3.15
  • MySQL Community Server 5.7.17
  • Oracle Database Express Edition 11g Release 2

GenerationType.IDENTITY

テーブルのidentity列を利用して,主キー値を生成します。

@Entity
@Table(name="users")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="userid")
    private long userId;

    @Column(name="username")
    private String userName;

    @Column(name="password")
    private String password;

    @Column(name="email")
    private String email;

    ...
}

PostgreSQLの場合は、関連するテーブルのカラムタイプを SERIAL にする必要があります。

CREATE TABLE users
(
    userid serial NOT NULL,
    username character varying,
    password character varying,
    email character varying,
    CONSTRAINT "PK" PRIMARY KEY (userid)
)

MySQLの場合は、カラムの属性にAUTO_INCREMENTを指定する必要があります。

Create TABLE users (
    userid bigint not null AUTO_INCREMENT PRIMARY KEY,
    username varchar(20),
    password varchar(20),
    email varchar(20)
);

Oracleは、GenerationType.IDENTITYをサポートしていません。

GenerationType.SEQUENCE

データベースのシーケンスオブジェクトを使用して,主キー値を生成します。

@Entity
@Table(name="users")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "userid_seq")
    @SequenceGenerator(name = "userid_seq", sequenceName = "userid_seq", allocationSize = 1)
    @Column(name="userid")
    private long userId;

    @Column(name="username")
    private String userName;

    @Column(name="password")
    private String password;

    @Column(name="email")
    private String email;

    ...
}

PostgreSQLの場合は、sequenceNameに指定されているシーケンスオブジェクトが必要です。

CREATE SEQUENCE userid_seq
    INCREMENT 1
    MINVALUE 1
    MAXVALUE 10000
    START 1
    CACHE 1
    CYCLE;

MySQLはシーケンスをサポートしないため、GenerationType.SEQUENCEを利用できません。

Oracleは、PostgreSQLと同様に指定されているシーケンスオブジェクトが必要です。

create sequence "USERID_SEQ"
    start with 1
    increment by 1
    maxvalue 10000
    minvalue 1
    nocache
    cycle
    noorder

GenerationType.TABLE

主キー値を保持しておくためのテーブルを使用して,主キー値を生成します。

@Entity
@Table(name="users")
public class User implements Serializable {

    @Id
    @TableGenerator( name = "seqTable", table = "seq_table", pkColumnName = "seq_name", pkColumnValue = "user_seq", valueColumnName = "seq_value", initialValue = 1, allocationSize = 1 )
    @GeneratedValue(strategy = GenerationType.TABLE, generator="seqTable")
    @Column(name="userid")
    private long userId;

    @Column(name="username")
    private String userName;

    @Column(name="password")
    private String password;

    @Column(name="email")
    private String email;

    ...
}

PostgreSQL、MySQLとOracleは何れも対応しているし、指定されているテーブルオブジェクトを作成する必要があります。

--postgresql
CREATE TABLE seq_table
(
    seq_name character varying NOT NULL,
    seq_value bigint,
    CONSTRAINT seq_pk PRIMARY KEY (seq_name)
)

GenerationType.AUTO

データベースごとに異なる方法を選択し,主キー値を生成します。

@Entity
@Table(name="users")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="userid")
    private long userId;

    @Column(name="username")
    private String userName;

    @Column(name="password")
    private String password;

    @Column(name="email")
    private String email;

    ...
}

PostgreSQLの場合は、シーケンスオブジェクトhibernate_sequenceを使います。このシーケンスが存在しない場合、org.postgresql.util.PSQLException: ERROR: リレーション"hibernate_sequence"は存在しませんのエラーメッセージが表示されます。

MySQLの場合は、GenerationType.IDENTITYと同じの動きをします。カラムの属性にAUTO_INCREMENTが指定されていない場合にjava.sql.SQLException: Field 'userid' doesn't have a default valueのエラーメッセージが表示されます。

Oracleの場合は、PostgreSQLと同じく、シーケンスオブジェクトhibernate_sequenceが使用されます。

118
105
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
118
105

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?