2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaのORM(Object-Relational Mapping)について

Posted at

はじめに

SpringBootで開発を行う際、DBとのデータ連携でentityRepositoryを使用し、CRUD操作を行っていると思います。

Entity

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity // このクラスがEntityであることを示す
public class User {

    @Id // 主キーであることを示す
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // GetterとSetter
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

Repository

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

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // findByEmailというメソッド名を定義するだけで、
    // "SELECT * FROM user WHERE email = ?" というSQLが自動生成される
    User findByEmail(String email);
}

SpringからSpringBootへ移行して、SQLを書かずにDBとのやり取りができたことにとてもびっくりしたのを覚えています。

ただその時は、経験が浅く、いろいろわからないことだらけだったため、なぜSQLを書かずにDBとやり取りができるのか、をしっかりと調べることをしませんでした。。。。ヨクナイ

ということで、今回JPA(Java Persistence API)やORMについて、まとめてみたいと思います。

ORM(Object-Relational Mapping)とは??

オブジェクトとデータベース間のマッピングを行う技術概念の総称。

JPA (Java Persistence API)とは?

JPAは、データベースを扱うための約束事を定めたものです。ルールブックみたいなもの。
「Javaのクラスに@Entityと書いたら、それはデータベースのテーブルだよ」「主キーは@Idと書いてね」といった、プログラマーが守るべき共通のルールが決められています。

JPAはそれ自体が動くものではなく、あくまで「どうやって作ればうまく動くか」という設計図のようなものです。

Hibernate とは?

Hibernateは、そのJPAのルールブックを完璧に理解し、実際に動くように作られた具体的なツールです。 優秀な職人のようなもの。
プログラマーが書いた@Entityアノテーションを見て、「これはCREATE TABLE文に変換すればいいな」と判断し、自動でSQL文を作成して実行してくれます。

つまり

  1. ORMは「技術

  2. JPAは、その技術をJavaで標準化するための「仕様

  3. Hibernateなどは、その仕様(JPA)に準拠した「実装

これにより、開発者はJPAのAPIを使ってコードを書けば、裏側で動作するORMフレームワークHibernateからEclipseLinkに切り替えても、コードをほとんど変更せずに済むというメリットがあります。

Repositoryを実行すると

裏側でHibernateが動いてSQL文を生成し、実行してくれます

これは、Spring Data JPAHibernateの連携によって実現される非常に便利な仕組みです。

  1. Repositoryの定義: 開発者は、データアクセスに必要なメソッド(findById(), save()など)を定義したRepositoryインターフェースを作成します。この時点では、具体的な実装は記述しません。

  2. Repositoryの実行: アプリケーションのビジネスロジック(サービス層など)から、このRepositoryインターフェースのメソッドを呼び出します。

  3. Hibernateの動作: Spring Data JPAは、呼び出されたメソッド名や引数などから、その操作に合ったSQL文をHibernateに生成させます。

  4. データベースへのアクセス: 生成されたSQL文がJDBCJava Database Connectivity)を介してデータベースに送信され、実行されます。

  5. 結果の返却: データベースから返された結果が、再びHibernateによってJavaのEntityオブジェクトに変換され、Repositoryを通じてアプリケーションに返されます。

この仕組みのおかげで、開発者は煩雑なSQL文を直接書く必要がなくなり、オブジェクト指向のコードに集中できるようになります。

具体的な実行の流れ(下記にソース例あり)

  1. ブラウザから/user?email=test@example.comというリクエストが送られる。

  2. UserControllerがリクエストを受け取る。

  3. UserControllerUserServicefindUserByEmailメソッドを呼び出す。

  4. UserServiceUserRepositoryfindByEmailメソッドを呼び出す。

  5. Spring Data JPAHibernateが連携し、SELECT * FROM user WHERE email = 'test@example.com'というSQL文を自動生成して実行する。

  6. データベースから取得したデータがUserオブジェクトに変換されて返される。

  7. UserControllerは、そのUserオブジェクトをmodel.addAttributeを使ってModelに格納する。

  8. user-details.html(View)にデータが渡され、ユーザー情報が表示される。

このように、開発者はSQLを一行も書かずにデータベース操作が実現できるのが、Spring BootRepositoryHibernate(ORM)の連携の大きなメリットです

具体的なソース例

Entity(データベースのテーブルに対応するクラス)

これは、データベースのusersテーブルに対応するUserクラスです。これがORMが扱うオブジェクト(Entity)です。

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity // このクラスがEntityであることを示す
public class User {

    @Id // 主キーであることを示す
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // GetterとSetter
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

Repository(データアクセスの窓口)

これは、User Entityを操作するためのRepositoryインターフェースです。Spring Data JPAが、このメソッド名から自動でSQLを生成します。

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

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // findByEmailというメソッド名を定義するだけで、
    // "SELECT * FROM user WHERE email = ?" というSQLが自動生成される
    User findByEmail(String email);
}

Service(ビジネスロジック層)

Serviceクラスは、Repositoryを使ってデータアクセスを行います。ここでは、UserRepositoryがインジェクション(注入)されています。

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

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public User findUserByEmail(String email) {
        // Repositoryのメソッドを呼び出すだけで、SQLは意識しない
        return userRepository.findByEmail(email);
    }
}

Controller(リクエストの処理)

Controllerは、Serviceを呼び出してビジネスロジックを実行し、その結果をModelに格納してViewに渡します。

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 org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/user")
    public String getUser(@RequestParam String email, Model model) {

        // Serviceを呼び出す
        User user = userService.findUserByEmail(email);

        // 結果をModelに格納
        model.addAttribute("user", user);

        // Thymeleafテンプレートに渡す
        return "user-details";
    }
}
2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?