23.

【Spring】@Tableアノテーションとは

編集
この記事の要点
  • @Table は JPA エンティティのDB テーブル名・スキーマ・インデックスを指定するアノテーション
  • デフォルトでクラス名 = テーブル名(snake_case 変換)
  • 主要属性: name / schema / catalog / indexes / uniqueConstraints
  • 指定しなくても動くが、明示することで命名規則の混乱を回避
  • スキーマ・複数 DB 環境で特に重要

 

基本的な使い方

@Entity
@Table(name = "users")
public class User {
    @Id @GeneratedValue
    private Long id;
    private String name;
}
// → "users" テーブルにマッピング

// 省略するとクラス名から推測
@Entity
public class UserProfile { }  // → "user_profile" テーブル

属性一覧

属性用途
nameテーブル名"users"
schemaスキーマ名"auth"
catalogカタログ名"company_db"
indexesインデックス定義@Index 配列
uniqueConstraintsUNIQUE 制約@UniqueConstraint 配列

スキーマの指定

// PostgreSQL / Oracle のスキーマ
@Entity
@Table(name = "users", schema = "auth")
public class User { }
// → SELECT * FROM auth.users

// 複数スキーマ運用
@Entity
@Table(name = "users", schema = "tenant_a")
public class TenantAUser { }

@Entity
@Table(name = "users", schema = "tenant_b")
public class TenantBUser { }

インデックスの定義

@Entity
@Table(name = "users",
    indexes = {
        @Index(name = "idx_users_email", columnList = "email", unique = true),
        @Index(name = "idx_users_status", columnList = "status"),
        @Index(name = "idx_users_created", columnList = "created_at"),
        @Index(name = "idx_users_status_role", columnList = "status, role"),  // 複合
    }
)
public class User { }

// 生成される DDL
// CREATE UNIQUE INDEX idx_users_email ON users(email);
// CREATE INDEX idx_users_status ON users(status);
// CREATE INDEX idx_users_created ON users(created_at);
// CREATE INDEX idx_users_status_role ON users(status, role);

UNIQUE 制約の定義

@Entity
@Table(name = "users",
    uniqueConstraints = {
        @UniqueConstraint(name = "uk_users_email", columnNames = "email"),
        @UniqueConstraint(name = "uk_users_tenant_username",
            columnNames = {"tenant_id", "username"})  // 複合 UNIQUE
    }
)
public class User { }

// 生成される DDL
// ALTER TABLE users ADD CONSTRAINT uk_users_email UNIQUE (email);
// ALTER TABLE users ADD CONSTRAINT uk_users_tenant_username UNIQUE (tenant_id, username);

命名規則のカスタマイズ

Spring Boot のデフォルトはキャメルケース → スネークケース変換。これを無効化したい場合:

# application.properties
# デフォルト: SpringPhysicalNamingStrategy (キャメル → スネーク)
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

# クラス名そのまま使いたい場合
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# → UserProfile クラス → UserProfile テーブル (スネーク変換なし)

# 完全カスタム
spring.jpa.hibernate.naming.physical-strategy=com.example.MyCustomNamingStrategy

複数 DB / @SecondaryTable(1 エンティティ複数テーブル)

// メインテーブル + 補助テーブル
@Entity
@Table(name = "users")
@SecondaryTable(name = "user_profiles", pkJoinColumns = @PrimaryKeyJoinColumn(name = "user_id"))
public class User {
    @Id @GeneratedValue
    private Long id;

    private String name;  // users.name

    @Column(table = "user_profiles", name = "bio")
    private String bio;   // user_profiles.bio

    @Column(table = "user_profiles", name = "birth_date")
    private LocalDate birthDate;  // user_profiles.birth_date
}

// 1 エンティティで 2 テーブル管理 (推奨されない、関連で分けた方が良い)

動的テーブル名(Multi-Tenant)

テナント別にテーブル名を変えたい場合は @Table ではなく Hibernate の MultiTenancy 機能を使用:

// application.properties
spring.jpa.properties.hibernate.multiTenancy=SCHEMA
spring.jpa.properties.hibernate.tenant_identifier_resolver=com.example.MyTenantResolver
spring.jpa.properties.hibernate.multi_tenant_connection_provider=com.example.MyConnectionProvider

// テナント解決
@Component
public class MyTenantResolver implements CurrentTenantIdentifierResolver {
    @Override
    public String resolveCurrentTenantIdentifier() {
        return TenantContext.getCurrentTenant();  // ThreadLocal 等から取得
    }
}

テーブル名衝突の回避

// 異なるパッケージで同名エンティティ
@Entity
@Table(name = "blog_posts")  // ← 明示しないと "post" 同士で衝突
package com.example.blog;
public class Post { }

@Entity
@Table(name = "news_posts")
package com.example.news;
public class Post { }

// SQL 上は別テーブルになり、JPQL は class で区別される

命名のベストプラクティス

  • スネークケース統一: user_profiles ◯、userProfiles ×
  • 複数形: テーブルは users 複数、エンティティは User 単数
  • プレフィックスは避ける: tbl_users ×、users
  • 明示的命名: @Table(name = "...") を必ず付ける(クラスリネーム時の安全性)
  • インデックスは命名規則を統一: idx_テーブル_カラム
  • UNIQUE は uk_ プレフィックス

注意点

  • DDL は Hibernate 自動生成: spring.jpa.hibernate.ddl-auto = update/create で生成
  • 本番は Flyway / Liquibase: Hibernate 自動 DDL は本番非推奨
  • schema 指定で接続先 DB の権限: SELECT 等の権限がないとエラー
  • カラムは @Column で別途指定: @Table はあくまでテーブルレベル

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. @After
  2. @Autowired
  3. @Bean
  4. @Before
  5. @Column
  6. @Component
  7. @Configuration
  8. @Controller
  9. @Data
  10. @Entity
  11. @GeneratedValue
  12. @Id
  13. @Modifying
  14. @PathVariable
  15. @PropertySource
  16. @Repository
  17. @RequestBody
  18. @RequestMapping
  19. @ResponseBody
  20. @RestController
  21. @Service
  22. @SpringBootApplication
  23. @Table
  24. @Transactional
  25. @Value