質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

MyBatis

MyBatisはJavaや.NET Frameworkでなどで使用できる、SQL文や、ストアドプロシージャをオブジェクトと紐付けるO/Rマッピングフレームワークです。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

14705閲覧

Spring + MyBatisでテーブル結合を実現する方法を知りたいです。

box_908

総合スコア5

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

MyBatis

MyBatisはJavaや.NET Frameworkでなどで使用できる、SQL文や、ストアドプロシージャをオブジェクトと紐付けるO/Rマッピングフレームワークです。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2020/09/27 13:18

編集2020/09/28 13:08

#やりたいこと
Spring + MyBatisでテーブル結合を実現したい。

#問題点
SQLのSELECT結果がnullで返却されること。

#ソース

schema

1DROP TABLE IF EXISTS detail CASCADE; 2DROP TABLE IF EXISTS player CASCADE; 3 4 5CREATE TABLE player 6( 7 id character NOT NULL , 8 name character varying(256), 9 age character varying(256), 10 detail_id character varying(256), 11 CONSTRAINT pkey PRIMARY KEY (id) 12); 13 14 15CREATE TABLE detail 16( 17 detail_id character NOT NULL , 18 work character varying(256), 19 CONSTRAINT ppkey PRIMARY KEY (detail_id) 20);

MyBatisMapper

1<select id="selectItem" resultMap="PlayerDetailMap"> 2 SELECT 3 p.id 4 ,p.name 5 ,d.work 6 FROM 7 player p 8 INNER JOIN 9 detail d 10 ON 11 p.detail_id=d.detail_id 12 WHERE 13 p.id=#{id} 14 </select> 15 16 <!-- テーブルのSELECT結果をどのようにマッピングするか指定 --> 17 <resultMap id="PlayerDetailMap" type="com.mybatis.test.domain.PlayerEntity"> 18 <id property="id" column="id" /> 19 <result property="name" column="name" /> 20 <collection property="detailEntity" ofType="com.mybatis.test.domain.DetailEntity"> 21 <result property="work" column="work" /> 22 </collection> 23 </resultMap>

結合する2つの元となるエンティティクラスは以下。

PlayerEntity

1@Entity 2public class PlayerEntity { 3 4 @Id 5 private String id; 6 7 private String name; 8 private String age; 9 private String detail_id; 10 @Transient 11 private List<DetailEntity> detailEntity;

DetailEntity

1@Entity 2public class DetailEntity { 3 4 @Id 5 private String detail_id; 6 private String work;

Controller

1@GetMapping() 2 public String index(Model model) { 3 PlayerDetailEntity playerDetailEntity = new PlayerDetailEntity(); 4 playerDetailEntity = myBatisService.selectItem("001"); 5 model.addAttribute("playerDetailEntity", playerDetailEntity); 6 return "index";

index

1<div th:object="${playerDetailEntity}"> 2 <div> 3 <label><b>名前</b></label> 4 <p th:text="*{name}"> 5 </div> 6 <div> 7 <label><b>仕事</b></label> 8 <p th:text="*{detailEntity.work}"> 9 </div> 10 </div>

MyBatisMapper.xmlの記述が問題だと思われるのですが、
どこがイケナイのかわかりません。
ご教示お願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

1:1の親子関係の場合

テーブルの親子関係は detail_id で結びついていますので、親Entityを以下に設定し、これの子をDetailとした場合は、次のように 子要素が1以上ありますので、List<Detail> detailIds として宣言します。

java

1import lombok.Data; 2 3@Data 4public class Player { 5 private String id; 6 private String name; 7 private String age; 8 private Detail detail; 9}

java

1import lombok.Data; 2 3@Data 4public class Detail { 5 private String detailId; 6 private String work; 7}

これを検索するSQL(SQLマッピング)は次のようになります。

xml

1<?xml version="1.0" encoding="UTF-8" ?> 2<!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5<mapper namespace="com.github.apz.mapper.PlayerMapper"> 6 <select id="findById" resultMap="playerMap"> 7 SELECT 8 player.id 9 , player.name 10 , player.age 11 , player.detail_id 12 , detail.work 13 FROM 14 player 15 JOIN DETAIL 16 ON player.detail_id = detail.detail_id 17 WHERE 18 player.id = #{id} 19 </select> 20 21 <resultMap type="com.github.apz.entity.Player" id="playerMap"> 22 <id property="id" column="id" /> 23 <result property="name" column="name" /> 24 <result property="age" column="age" /> 25 <association property="detail" resultMap="detailResult"/> 26 </resultMap> 27 28 <resultMap id="detailResult" type="com.github.apz.entity.Detail"> 29 <result property="detailId" column="detail_id" /> 30 <result property="work" column="work" /> 31 </resultMap> 32</mapper>

ポイントとなる点ですが、

テーブルを結合する条件(今回は detail_id)を必ずSQLに盛り込みます。
検索の結果は resultMap要素で別途定義します。

<resultMap>では、実際に検索結果で得たい内容(今回はPlayer)に対する結果のマッピングを行います。 property は Javaクラス側のプロパティ(変数) columnはSQLのカラムです。

テーブル結合の条件となっている detail_id の記述方法ですが、親要素である player の detail が子要素を持つことをPlayerクラスで宣言していている状態を記述します。

propertyで、子クラスを束ねる親クラスのフィールド名 detail であり、その内容は type で宣言したクラスで、この2つのマッピングの関係は、resultMapのid="detailResult" で関連づけられます。

1:Nのリレーション関係にある検索結果のマッピングについては https://qiita.com/alpha_pz/items/9c88acd814ffad2f1a36 を参考にしてください。

投稿2020/09/27 13:26

編集2020/09/29 13:12
A-pZ

総合スコア12011

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

box_908

2020/09/28 11:36

ご回答ありがとうございます。 Qiita拝見させていただきました。 申し訳ないですが、参考にさせて頂いて、試行してみましたが、正常に動作しません。 不足している修正箇所はどこになるでしょうか。
A-pZ

2020/09/28 11:46

SQLの検索結果にdetail_id がないようですが、こちらは追加して試されましたでしょうか。
box_908

2020/09/28 11:49

ご親切にありがとうございます。 はい、追加しましたが、まだのようです。
A-pZ

2020/09/28 12:25

なるほど、少しお待ちください。
box_908

2020/09/28 12:30

すみません。お手数をお掛けします。 ソース修正したのを更新しました。
A-pZ

2020/09/28 12:40

あとお手数ですが、テーブル定義もあわせて記載いただけると助かります。ちなみに結合する2つのエンティティですが、親:子=1:Nの関係でしょうか?
box_908

2020/09/28 13:09

内容更新しました。 親:子=1:1の関係になります。 よろしくお願いします。
A-pZ

2020/09/28 13:10

ありがとうございます、お待ちください。
box_908

2020/09/28 23:18

ご丁寧にありがとうございます。本当に助かります。 ご質問ですが、Entityを@Dataにしなくては、実現できないものでしょうか?
A-pZ

2020/09/29 00:18

@DataはLombokのアノテーションで、get/setメソッドがあればよいです。 ちなみに回答の先頭にも記載しておりますが、JPAのアノテーション(????Entityや????Id)は利用しません(効果がありません)
A-pZ

2020/09/29 11:48

こちらの実行結果は試されましたでしょうか。
box_908

2020/09/29 11:52

SQL自体は動きました! ありがとうございます。 度々申し訳ございません。 取得した項目(work)はいまのindexファイルの指定方法だと読み取ってもらえず、 どのような記載が正しいのでしょうか?
A-pZ

2020/09/29 12:06

index?ファイルとは、MyBatisのSQLファイルを記述しているxmlファイルのことであってますでしょうか。 私の回答で記述した内容ですと、Playerクラスに List<Detail> detailIds; にdetailテーブルを結合した内容が入っていますので(今回の場合は、常に1件しか入らないと思います) Detail detail = detailIds.get(0); で取得し、detail.getWork() で取得できるかと思います。
box_908

2020/09/29 12:16

画面に出力するために私が作成したindex.htmlのことです。 コントローラーで player = myBatisService.selectItem("002");のように取得したのち、 player.getDetailIds().get(0).getWork();をして、ほしい項目を取得する方法しかないということでしょうか? model.addAttribute("playerDetail", player);でオブジェクトを詰めて そのままindex.htmlでth:object="${playerDetail}"で値を出力したかったのです。
A-pZ

2020/09/29 13:00

なるほど画面ですね、失礼しました。 PlayerクラスからplayerDetailへのアクセスは、現在の実装(1:N)の場合はそのように、getDetailIds().get(0).getWork() になります。 ただ、今回のように、1:1の関係しかないのでしたら、Listに詰め替える処理にしないで、直接 playerDetail で取得する方に切り替えた方がよさそうですね。回答を編集しますのでお待ちください。
box_908

2020/09/29 13:09

わざわざすみません。 ありがとうございます。
A-pZ

2020/09/29 13:12

こちら回答を編集いたしましたのでご確認ください。お手数をおかけします。
box_908

2020/09/29 13:31

ありがとうございます!出来ました。 ご丁寧に教えて頂いてありがとうございます。 association 使用する際は、resultMap で子要素を対応づけるのですね。
A-pZ

2020/09/29 13:33

ですです。resultMapを複数つなげるときに使えます。SQLの実装を大きく変えることなくJavaへのマッピングを切り変えるときにも有効です。
box_908

2020/09/29 22:54

慣れるまで、時間かかりそうですが、勉強します! 今回は本当にありがとうございました。 また、機会があれば何卒宜しくお願い致します。
A-pZ

2020/09/30 02:04

d(・ω・今回は長時間にわたってしまい失礼しました。こちらこそよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問