Spring Boot

Spring Boot + JPAで複合主キーのテーブルを扱う方法

2021年7月15日

はじめに

Javaのフレームワーク「Spring Boot」とデータベース操作を簡単に利用できる「Spring Data JPA」を使い、複合主キー(テーブルに複数の主キーがある)のテーブルからデータを抽出する方法を紹介します。

本記事で作成する「一覧画面」のイメージとテーブル定義は以下の通り。

生徒情報一覧

[テーブル定義]

物理名論理名データ型NOT NULL説明
school_year学年INT主キー
groupINT主キー
number出席番号INT主キー
name名前VARCHAR(100)生徒の名前

[CREATE文]

CREATE TABLE `sampledb`.`student` (
  `school_year` int NOT NULL,
  `group` int NOT NULL,
  `number` int NOT NULL,
  `name` varchar(100) NOT NULL,
  PRIMARY KEY (`school_year`,`group`,`number`)
);

[INSERT文]

INSERT INTO `sampledb`.`student` (`school_year`, `group`, `number`, `name`) VALUES ('1', '1', '1', '鈴木一郎');
INSERT INTO `sampledb`.`student` (`school_year`, `group`, `number`, `name`) VALUES ('1', '1', '2', '佐藤二郎');
INSERT INTO `sampledb`.`student` (`school_year`, `group`, `number`, `name`) VALUES ('1', '1', '3', '田中三郎');
INSERT INTO `sampledb`.`student` (`school_year`, `group`, `number`, `name`) VALUES ('1', '3', '1', '伊藤四郎');

スポンサーリンク

開発環境

開発環境は以下のとおり。

開発環境名称説明
開発言語Java人気の開発言語
開発ツールEclipseJavaでの定番開発ツール
フレームワークSpring Boot人気のSpringフレームワークをベースとしたフレームワーク
テンプレートエンジンThymeleafSpring Bootと相性が良いテンプレートエンジン
データベースMySQLフリーで利用できる人気データベース

ディレクトリ構成

ディレクトリ構成は以下のとおり。

springSample
  |
  |___src.main.java
       |
       |___com.example.demo
       |    |
       |    |___controller
       |    |    |
       |    |    |__StudentController.java
       |    |
       |    |___entity
       |    |    |
       |    |    |___Student.java
       |    |    |
       |    |    |___StudentKey.java
       |    |
       |    |___repository
       |    |    |
       |    |    |___StudentRepository.java
       |    |
       |    |___service
       |         |
       |         |___StudentService.java
       |
       |___src.main.resources
            |
            |___templates
            |    |
            |    |___student
            |         |
            |         |___list.html
            |
            |___static
                 |
                 |___css
                      |
                      |___list.css

バックエンド(サーバー)側のソースコード

エンティティクラス(Student.java)

データベースから取得したデータを格納するエンティティクラスの内容は以下の通り。@Dataアノテーションを使用して、getter、setterの定義を省略しています。

また、@IdClassでPrimaryKeyを定義したクラスを指定します。

package com.example.demo.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;

import lombok.Data;

/**
 * 生徒情報 Entity
 */
@Entity
@Data
@Table(name="student")
@IdClass(value=StudentKey.class)
public class Student implements Serializable {

  /**
   * 学年
   */
  @Id
  @Column(name="school_year")
  private int schoolYear;
  /**
   * 組
   */
  @Id
  @Column(name="group")
  private int group;
  /**
   * 出席番号
   */
  @Id
  @Column(name="number")
  private int number;
  /**
   * 名前
   */
  @Column(name="name")
  private String name;
}

PrimaryKeyを定義したクラス(StudentKey.java)

複合主キーのテーブルを扱う場合は、PrimaryKeyを定義したクラスを作る必要があります。

package com.example.demo.entity;

import java.io.Serializable;

import lombok.Data;

/**
 * 生徒情報の主キー用 Entity
 */
@Data
public class StudentKey implements Serializable {

  /**
   * 学年
   */
  private int schoolYear;
  /**
   * 組
   */
  private int group;
  /**
   * 出席番号
   */
  private int number;
}

リポジトリクラス(StudentRepository.java)

データベースにアクセスする為のリポジトリクラスの内容は以下の通り。JpaRepositoryには、JpaRepository<Student, StudentKey>のようにエンティティクラスとPrimaryKeyを定義したクラスを指定します。

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.demo.entity.Student;
import com.example.demo.entity.StudentKey;

/**
 * 生徒情報 Repository
 */
@Repository
public interface StudentRepository extends JpaRepository<Student, StudentKey> {}

サービスクラス(StudentService.java)

サービスクラスの内容は以下の通り。サービスクラスでは、Spring Data JPAで用意されている「findAll()」を使いテーブルの内容を全件取得しています。

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.entity.Student;
import com.example.demo.repository.StudentRepository;

/**
 * 生徒情報 Service
 */
@Service
public class StudentService {

  /**
   * 生徒情報 Repository
   */
  @Autowired
  private StudentRepository studentRepository;

  /**
   * 生徒情報 全検索
   * @return 検索結果
   */
  public List<Student> searchAll() {
    return studentRepository.findAll();
  }
}

コントローラークラス(StudentController.java)

コントローラクラスの内容は以下の通り。

package com.example.demo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;

/**
 * 生徒情報 Controller
 */
@Controller
public class StudentController {

  /**
   * 生徒情報Service
   */
  @Autowired
  private StudentService studentService;

  /**
   * 生徒情報一覧画面を表示
   * @param model Model
   * @return 生徒情報一覧画面
   */
  @GetMapping(value = "/student/list")
  public String displayList(Model model) {
    List<Student> studentlist = studentService.searchAll();
      model.addAttribute("studentlist", studentlist);
      return "student/list";
  }
}

フロントエンド(クライアント)側のソースコード

スポンサーリンク

HTML(list.html)

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>生徒情報一覧</title>
    <link href="/css/list.css" rel="stylesheet"></link>
    <meta charset="utf-8" />
  </head>
  <body>
    <h1>生徒情報一覧</h1>
  <table>
    <thead>
      <tr>
        <th>学年</th>
        <th>組</th>
        <th>出席番号</th>
        <th>名前</th>
      </tr>
    </thead>
    <tbody>
        <tr th:each="student : ${studentlist}" th:object="${student}">
            <td class="center" th:text="*{schoolYear}"></td>
            <td class="center" th:text="*{group}"></td>
            <td class="center" th:text="*{number}"></td>
            <td th:text="*{name}"></td>
        </tr>
      </tbody>
  </table>
  </body>
</html>

スタイルシート(list.css)

body {
  width: 90%;
}
table{
    width: 100%;
    border-collapse: collapse;
  font-size: 12px;
}
table th, table td {
    border: 1px solid #ddd;
    padding: 6px;
}
table th {
  background-color: #F2F2F2;
}
.center {
  text-align: center;
}

動作確認

Spring Bootプロジェクトを実行して http://localhost:8080/student/list へアクセスします。

一覧画面が表示され、デーベースから取得した値が一覧に表示されていれば完了です。

生徒情報一覧

helpful