LoginSignup
0
3

More than 1 year has passed since last update.

Spring O/R Mapperの使い分け

Last updated at Posted at 2022-04-09

O/R Mapperとは何か

O/R Mapperはオブジェクト指向言語で書かれたアプリケーションと非オブジェクト指向であるデータベースやSQLの間のインピーダンスミスマッチを解消させるためのフレームワークである。今回はメジャーなO/RMapperである以下のフレームワークについて調査する。

  • JPA(Java Persistance API)
  • MyBatis

JPA(Java Persistance API)

  • Domainに@Entity等のアノテーションを付与することで設定する
  • CRUDに関わる基本的なメソッドがEntityManagerから提供されるため、冗長なSQLの記載が不要になる
  • 独自のクエリを発行する際は、SQLライクな独自のクエリ言語であるJPQL(Java Persistance Query Language)を使用する

以下にDomainの実装例を示す。

package com.example.todo.domain.model;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "todo")
public class Todo implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "todo_id")
    private String todoId;
    @Column(name = "todo_title")
    private String todoTitle;
    @Column(name = "finished")
    private boolean finished;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at")
    private Date createdAt;
    public String getTodoId() {
        return todoId;
    }
    public void setTodoId(String todoId) {
        this.todoId = todoId;
    }
    public String getTodoTitle() {
        return todoTitle;
    }
    public void setTodoTitle(String todoTitle) {
        this.todoTitle = todoTitle;
    }
    public boolean isFinished() {
        return finished;
    }
    public void setFinished(boolean finished) {
        this.finished = finished;
    }
    public Date getCreatedAt() {
        return createdAt;
    }
    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }
}

以下にRepositoryの実装例を示す。 なお、RepositoryImplは自動生成されるため作成不要である。

package com.example.todo.domain.repository.todo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.example.todo.domain.model.Todo;

public interface TodoRepository extends JpaRepository<Todo, String> {

    @Query("SELECT COUNT(t) FROM Todo t WHERE t.finished = :finished")
    long countByFinished(@Param("finished") boolean finished);

}

MyBatis

  • O/R MapperというよりもSQLとオブジェクトをマッピングするSQL Mapperという表現が正しい
  • Mapperファイル(xml)にSQLとオブジェクトのメソッドとのマッピングを定義する
  • SQLでデータベースの操作ができつつも、ビジネスロジックからSQL自体を隠蔽できる

以下にMapperファイルの例を示す。 なお、Repositoryについては通常と同様にエンティティとプロパティを定義する。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.todo.domain.repository.todo.TodoRepository">

    <resultMap id="todoResultMap" type="Todo">
        <id property="todoId" column="todo_id" />
        <result property="todoTitle" column="todo_title" />
        <result property="finished" column="finished" />
        <result property="createdAt" column="created_at" />
    </resultMap>

    <select id="findById" parameterType="String" resultMap="todoResultMap">
    <![CDATA[
        SELECT
            todo_id,
            todo_title,
            finished,
            created_at
        FROM
            todo
        WHERE
            todo_id = #{todoId}
    ]]>
    </select>

    <select id="findAll" resultMap="todoResultMap">
    <![CDATA[
        SELECT
            todo_id,
            todo_title,
            finished,
            created_at
        FROM
            todo
    ]]>
    </select>

    <insert id="create" parameterType="Todo">
    <![CDATA[
        INSERT INTO todo
        (
            todo_id,
            todo_title,
            finished,
            created_at
        )
        VALUES
        (
            #{todoId},
            #{todoTitle},
            #{finished},
            #{createdAt}
        )
    ]]>
    </insert>

    <update id="update" parameterType="Todo">
    <![CDATA[
        UPDATE todo
        SET
            todo_title = #{todoTitle},
            finished = #{finished},
            created_at = #{createdAt}
        WHERE
            todo_id = #{todoId}
    ]]>
    </update>

    <delete id="delete" parameterType="Todo">
    <![CDATA[
        DELETE FROM
            todo
        WHERE
            todo_id = #{todoId}
    ]]>
    </delete>

    <select id="countByFinished" parameterType="Boolean"
        resultType="Long">
    <![CDATA[
        SELECT
            COUNT(*)
        FROM
            todo
        WHERE
            finished = #{finished}
    ]]>
    </select>

</mapper>

MyBatisとJPAの使い分け

  • 複雑なクエリが必要であり、今後もカスタマイズが想定される場合はカスタマイズ性の高いMyBatisを使用する
  • 単純なクエリしか必要ない、即座にモックアップ的なアプリケーションを構築する場合はJPAを使用する
  • JPAの場合、JPQLという独自のクエリ言語を用いるため、JPAに習熟している開発者が必要になる

参考文献

0
3
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
0
3