やりたいこと
- associationを使ってみたい
- 前回はresultMap / constructor を使ったマッピングをやってみたのでその続き
前提
実行環境
検証
DBテーブルの追加/更新
- 部署を管理するための
DIVISION
テーブルを追加
USERS
テーブルにDIVISION
テーブルを参照するカラムを追加
--- a/sql/001_init_tables.sql
+++ b/sql/001_init_tables.sql
@@ -1,9 +1,22 @@
+CREATE TABLE DIVISION (
+ DIVISION_ID CHAR(2) NOT NULL,
+ DIVISION_NAME VARCHAR(32) NOT NULL,
+ PRIMARY KEY (DIVISION_ID)
+);
+
+INSERT INTO DIVISION (DIVISION_ID, DIVISION_NAME) VALUES ('10', '人事部');
+INSERT INTO DIVISION (DIVISION_ID, DIVISION_NAME) VALUES ('20', '営業部');
+INSERT INTO DIVISION (DIVISION_ID, DIVISION_NAME) VALUES ('30', '開発部');
+
CREATE TABLE USERS (
USER_ID VARCHAR(32) NOT NULL,
FIRST_NAME VARCHAR(32) NOT NULL,
FAMILY_NAME VARCHAR(32) NOT NULL,
- PRIMARY KEY (USER_ID)
+ DIVISION_ID CHAR(2) NOT NULL,
+ PRIMARY KEY (USER_ID),
+ FOREIGN KEY (DIVISION_ID) REFERENCES DIVISION (DIVISION_ID)
);
-INSERT INTO USERS (USER_ID, FIRST_NAME, FAMILY_NAME) VALUES ('hogefuga', 'ほげ', 'ふが');
-INSERT INTO USERS (USER_ID, FIRST_NAME, FAMILY_NAME) VALUES ('foobar', 'ふー', 'ばー');
+
+INSERT INTO USERS (USER_ID, FIRST_NAME, FAMILY_NAME, DIVISION_ID) VALUES ('hogefuga', 'ほげ', 'ふが', '10');
+INSERT INTO USERS (USER_ID, FIRST_NAME, FAMILY_NAME, DIVISION_ID) VALUES ('foobar', 'ふー', 'ばー', '20');
Division / DivisionId クラスの追加
public class DivisionId {
private final String id;
public DivisionId(final String id) {
this.id = id;
}
public String toString() {
return id;
}
}
public class Division {
private final DivisionId divisionId;
private final String divisionName;
public Division(final DivisionId divisionId, final String divisionName) {
this.divisionId = divisionId;
this.divisionName = divisionName;
}
public String toString() {
return String.format("Division {%s:%s}", divisionId, divisionName);
}
}
UserクラスにDivisionクラスのフィールドを追加
--- a/core/src/main/java/com/github/nkiri/core/domain/model/user/User.java
+++ b/core/src/main/java/com/github/nkiri/core/domain/model/user/User.java
@@ -1,11 +1,15 @@
package com.github.nkiri.core.domain.model.user;
+import com.github.nkiri.core.domain.model.division.Division;
+
public class User {
private final UserId userId;
private final String firstName;
private final String familyName;
+ private Division division;
+
public User(final UserId userId, final String firstName, final String familyName) {
this.userId = userId;
this.firstName = firstName;
@@ -14,6 +18,7 @@ public class User {
public String toString() {
return String.format(
- "User {userId: %s, firstName: %s, familyName: %s}", userId, firstName, familyName);
+ "User {userId: %s, firstName: %s, familyName: %s, division: %s}",
+ userId, firstName, familyName, division);
}
}
UserMapper.xmlの修正 (本題)
- Userクラスのコンストラクタでセットしないフィールドに値をセットするときにassociationを使う
- 公式ドキュメントによると
has-one
のリレーションシップを扱うものだとのこと
- 使い方は
resultMap
と同じような感じ
<association>
要素の select
属性を使うこともできるけど、N+1問題が発生するので巨大な結果を取得するような場合は注意が必要そう
--- a/core/src/main/resources/com/github/nkiri/core/infrastructure/datastore/UserMapper.xml
+++ b/core/src/main/resources/com/github/nkiri/core/infrastructure/datastore/UserMapper.xml
@@ -4,10 +4,14 @@
<mapper namespace="com.github.nkiri.core.infrastructure.datastore.UserMapper">
<select id="get" resultMap="userResultMap">
SELECT
- USER_ID as userId
- , FIRST_NAME as firstName
- , FAMILY_NAME as familyName
- FROM USERS
+ u.USER_ID as userId
+ , u.FIRST_NAME as firstName
+ , u.FAMILY_NAME as familyName
+ , d.DIVISION_ID as divisionId
+ , d.DIVISION_NAME as divisionName
+ FROM USERS u
+ JOIN DIVISION d
+ ON u.DIVISION_ID = d.DIVISION_ID
<where>
USER_ID = #{id}
</where>
@@ -20,11 +24,23 @@
</constructor>
</resultMap>
+ <resultMap id="divisionIdMap" type="com.github.nkiri.core.domain.model.division.DivisionId">
+ <constructor>
+ <idArg column="divisionId" javaType="string"/>
+ </constructor>
+ </resultMap>
+
<resultMap id="userResultMap" type="com.github.nkiri.core.domain.model.user.User">
<constructor>
<idArg resultMap="userIdResultMap" column="userId" javaType="com.github.nkiri.core.domain.model.user.UserId"/>
<arg column="firstName" javaType="string"/>
<arg column="familyName" javaType="string"/>
</constructor>
+ <association property="division" javaType="com.github.nkiri.core.domain.model.division.Division">
+ <constructor>
+ <idArg column="divisionId" resultMap="divisionIdMap" javaType="com.github.nkiri.core.domain.model.division.DivisionId"/>
+ <arg column="divisionName" javaType="string"/>
+ </constructor>
+ </association>
</resultMap>
</mapper>