Spring Boot DB連携

Spring BootでDomaを利用してみた

Domaとは、S2Daoのスタイル(DAOパターンや2 Way SQL)を踏襲したJava6(JDBC4.0)対応のO/Rマッパーで、Springフレームワークに組み込んで使うことができる。今回は、MyBatisの代わりにDomaを利用するよう変更してみたので、そのサンプルプログラムを共有する。

前提条件

下記記事の実装が完了していること。

MyBatisのSQL文をXMLファイルに配置してみたMyBatisを利用するプログラムで、これまではMapperクラスに直接SQL文を記載していたが、今回はXMLファイルにSQL文を移動し...



サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、前提条件のプログラムから追加/変更したプログラムである。

build.gradleの内容は以下の通りで、Domaのライブラリを追加すると共に、copySqlタスクを追加している。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
plugins {
id 'org.springframework.boot' version '2.1.7.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
compile files('lib/ojdbc6.jar')
// Domaのインストール
implementation 'org.seasar.doma.boot:doma-spring-boot-starter:1.4.0'
annotationProcessor 'org.seasar.doma:doma-processor:2.35.0'
}
// ビルド前に実行する、SQLファイルをクラスパスにコピーする処理
task copySql(type: Copy) {
from './src/main/resources/META-INF'
into './build/classes/java/main/META-INF'
}
plugins { id 'org.springframework.boot' version '2.1.7.RELEASE' id 'java' } apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' compileOnly 'org.projectlombok:lombok:1.18.10' annotationProcessor 'org.projectlombok:lombok:1.18.10' compile files('lib/ojdbc6.jar') // Domaのインストール implementation 'org.seasar.doma.boot:doma-spring-boot-starter:1.4.0' annotationProcessor 'org.seasar.doma:doma-processor:2.35.0' } // ビルド前に実行する、SQLファイルをクラスパスにコピーする処理 task copySql(type: Copy) { from './src/main/resources/META-INF' into './build/classes/java/main/META-INF' }
plugins {
	id 'org.springframework.boot' version '2.1.7.RELEASE'
	id 'java'
}

apply plugin: 'io.spring.dependency-management'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	compileOnly 'org.projectlombok:lombok:1.18.10'
	annotationProcessor 'org.projectlombok:lombok:1.18.10'
	compile files('lib/ojdbc6.jar')
	// Domaのインストール
	implementation 'org.seasar.doma.boot:doma-spring-boot-starter:1.4.0'
	annotationProcessor 'org.seasar.doma:doma-processor:2.35.0'
}

// ビルド前に実行する、SQLファイルをクラスパスにコピーする処理
task copySql(type: Copy) {
	from './src/main/resources/META-INF'
	into './build/classes/java/main/META-INF'
}
サラリーマン型フリーランスSEという働き方でお金の不安を解消しよう先日、「サラリーマン型フリーランスSE」という働き方を紹介するYouTube動画を視聴しましたので、その内容をご紹介します。 「サ...

また、今回アクセスするテーブル(user_data)のエンティティクラスの内容は以下の通りで、テーブル名・カラム名や主キー設定を行っている。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package com.example.demo;
import lombok.Data;
import org.seasar.doma.Table;
import org.seasar.doma.Entity;
import org.seasar.doma.Id;
import org.seasar.doma.Column;
/**
* ユーザーデータテーブル(user_data)アクセス用エンティティ
*/
@Table(name = "user_data")
@Entity
@Data
public class UserData {
/** ID */
@Id
private long id;
/** 名前 */
private String name;
/** 生年月日_年 */
@Column(name="birth_year")
private int birthY;
/** 生年月日_月 */
@Column(name="birth_month")
private int birthM;
/** 生年月日_日 */
@Column(name="birth_day")
private int birthD;
/** 性別 */
private String sex;
}
package com.example.demo; import lombok.Data; import org.seasar.doma.Table; import org.seasar.doma.Entity; import org.seasar.doma.Id; import org.seasar.doma.Column; /** * ユーザーデータテーブル(user_data)アクセス用エンティティ */ @Table(name = "user_data") @Entity @Data public class UserData { /** ID */ @Id private long id; /** 名前 */ private String name; /** 生年月日_年 */ @Column(name="birth_year") private int birthY; /** 生年月日_月 */ @Column(name="birth_month") private int birthM; /** 生年月日_日 */ @Column(name="birth_day") private int birthD; /** 性別 */ private String sex; }
package com.example.demo;

import lombok.Data;
import org.seasar.doma.Table;
import org.seasar.doma.Entity;
import org.seasar.doma.Id;
import org.seasar.doma.Column;

/**
 * ユーザーデータテーブル(user_data)アクセス用エンティティ
 */
@Table(name = "user_data")
@Entity
@Data
public class UserData {

    /** ID */
    @Id
    private long id;

    /** 名前 */
    private String name;

    /** 生年月日_年 */
    @Column(name="birth_year")
    private int birthY;

    /** 生年月日_月 */
    @Column(name="birth_month")
    private int birthM;

    /** 生年月日_日 */
    @Column(name="birth_day")
    private int birthD;

    /** 性別 */
    private String sex;

}



さらに、今回アクセスするテーブル(user_data)のDaoインタフェースの内容は以下の通りで、「@ConfigAutowireable」「@Dao」アノテーションを先頭に付与し、各メソッドに「@Select」「@Delete」「@Update」「@Insert」アノテーションのいずれかを付与している。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package com.example.demo;
import org.seasar.doma.Dao;
import org.seasar.doma.Select;
import org.seasar.doma.Delete;
import org.seasar.doma.Insert;
import org.seasar.doma.Update;
import org.seasar.doma.boot.ConfigAutowireable;
import java.util.List;
@ConfigAutowireable
@Dao
public interface UserDataDao {
/**
* ユーザーデータテーブル(user_data)を全件取得する
* @return ユーザーデータテーブル(user_data)を全データ
*/
@Select
List<UserData> findAll();
/**
* 指定したIDをもつユーザーデータテーブル(user_data)のデータを取得する
* @param id ID
* @return ユーザーデータテーブル(user_data)の指定したIDのデータ
*/
@Select
UserData findById(Long id);
/**
* 指定したIDをもつユーザーデータテーブル(user_data)のデータを削除する
* @param userData ユーザーデータテーブル(user_data)の削除データ
*/
@Delete
int deleteById(UserData userData);
/**
* 指定したユーザーデータテーブル(user_data)のデータを追加する
* @param userData ユーザーデータテーブル(user_data)の追加データ
*/
@Insert
int create(UserData userData);
/**
* 指定したユーザーデータテーブル(user_data)のデータを更新する
* @param userData ユーザーデータテーブル(user_data)の更新データ
*/
@Update
int update(UserData userData);
/**
* ユーザーデータテーブル(user_data)の最大値IDを取得する
* @return ユーザーデータテーブル(user_data)の最大値ID
*/
@Select
long findMaxId();
}
package com.example.demo; import org.seasar.doma.Dao; import org.seasar.doma.Select; import org.seasar.doma.Delete; import org.seasar.doma.Insert; import org.seasar.doma.Update; import org.seasar.doma.boot.ConfigAutowireable; import java.util.List; @ConfigAutowireable @Dao public interface UserDataDao { /** * ユーザーデータテーブル(user_data)を全件取得する * @return ユーザーデータテーブル(user_data)を全データ */ @Select List<UserData> findAll(); /** * 指定したIDをもつユーザーデータテーブル(user_data)のデータを取得する * @param id ID * @return ユーザーデータテーブル(user_data)の指定したIDのデータ */ @Select UserData findById(Long id); /** * 指定したIDをもつユーザーデータテーブル(user_data)のデータを削除する * @param userData ユーザーデータテーブル(user_data)の削除データ */ @Delete int deleteById(UserData userData); /** * 指定したユーザーデータテーブル(user_data)のデータを追加する * @param userData ユーザーデータテーブル(user_data)の追加データ */ @Insert int create(UserData userData); /** * 指定したユーザーデータテーブル(user_data)のデータを更新する * @param userData ユーザーデータテーブル(user_data)の更新データ */ @Update int update(UserData userData); /** * ユーザーデータテーブル(user_data)の最大値IDを取得する * @return ユーザーデータテーブル(user_data)の最大値ID */ @Select long findMaxId(); }
package com.example.demo;

import org.seasar.doma.Dao;
import org.seasar.doma.Select;
import org.seasar.doma.Delete;
import org.seasar.doma.Insert;
import org.seasar.doma.Update;
import org.seasar.doma.boot.ConfigAutowireable;
import java.util.List;

@ConfigAutowireable
@Dao
public interface UserDataDao {

    /**
     * ユーザーデータテーブル(user_data)を全件取得する
     * @return ユーザーデータテーブル(user_data)を全データ
     */
    @Select
    List<UserData> findAll();

    /**
     * 指定したIDをもつユーザーデータテーブル(user_data)のデータを取得する
     * @param id ID
     * @return ユーザーデータテーブル(user_data)の指定したIDのデータ
     */
    @Select
    UserData findById(Long id);

    /**
     * 指定したIDをもつユーザーデータテーブル(user_data)のデータを削除する
     * @param userData ユーザーデータテーブル(user_data)の削除データ
     */
    @Delete
    int deleteById(UserData userData);

    /**
     * 指定したユーザーデータテーブル(user_data)のデータを追加する
     * @param userData ユーザーデータテーブル(user_data)の追加データ
     */
    @Insert
    int create(UserData userData);

    /**
     * 指定したユーザーデータテーブル(user_data)のデータを更新する
     * @param userData ユーザーデータテーブル(user_data)の更新データ
     */
    @Update
    int update(UserData userData);

    /**
     * ユーザーデータテーブル(user_data)の最大値IDを取得する
     * @return ユーザーデータテーブル(user_data)の最大値ID
     */
    @Select
    long findMaxId();
}
ウズウズカレッジJavaコースはわかりやすい動画教材と充実した就業サポートで優良企業を目指せるプログラミングスクールだったJavaは、世界中で広く使われていて、現在の需要が高く将来性もある開発言語になります。 https://www.acrovision....

また、SQLファイルの内容は以下の通りで、Daoインタフェースで「@Select」アノテーションを付与したメソッドに対応するSQL文をそれぞれ記載している。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
SELECT
id
, name
, birth_year
, birth_month
, birth_day
, sex
FROM USER_DATA
ORDER BY id
SELECT id , name , birth_year , birth_month , birth_day , sex FROM USER_DATA ORDER BY id
SELECT
      id
    , name
    , birth_year
    , birth_month
    , birth_day
    , sex
FROM USER_DATA
ORDER BY id
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
SELECT
id
, name
, birth_year
, birth_month
, birth_day
, sex
FROM USER_DATA
WHERE id = /* id */1
SELECT id , name , birth_year , birth_month , birth_day , sex FROM USER_DATA WHERE id = /* id */1
SELECT
      id
    , name
    , birth_year
    , birth_month
    , birth_day
    , sex
FROM USER_DATA
WHERE id = /* id */1
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
SELECT NVL(max(id), 0)
FROM USER_DATA
SELECT NVL(max(id), 0) FROM USER_DATA
SELECT NVL(max(id), 0)
FROM USER_DATA

なお、今回のサンプルでは使用していないが、「@Delete」「@Update」「@Insert」アノテーションでsqlFile属性をtrueにした場合も、SQLファイルが必要になる。



さらに、サービスクラスの実装クラスの内容は以下の通りで、先ほどのDaoインタフェースを呼び出すように修正している。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Service
public class DemoServiceImpl implements DemoService{
/**
* ユーザーデータテーブル(user_data)へアクセスするマッパー
*/
@Autowired
private UserDataDao userDataDao;
/**
* {@inheritDoc}
*/
@Override
public List<DemoForm> demoFormList() {
List<DemoForm> demoFormList = new ArrayList<>();
//ユーザーデータテーブル(user_data)から全データを取得する
Collection<UserData> userDataList = userDataDao.findAll();
for (UserData userData : userDataList) {
demoFormList.add(getDemoForm(userData));
}
return demoFormList;
}
/**
* {@inheritDoc}
*/
@Override
public DemoForm findById(String id) {
Long longId = stringToLong(id);
UserData userData = userDataDao.findById(longId);
return getDemoForm(userData);
}
/**
* {@inheritDoc}
*/
@Override
@Transactional(readOnly = false)
public void deleteById(String id){
UserData userData = new UserData();
userData.setId(stringToLong(id));
userDataDao.deleteById(userData);
}
/**
* {@inheritDoc}
*/
@Override
@Transactional(readOnly = false)
public void createOrUpdate(DemoForm demoForm){
//更新・追加処理を行うエンティティを生成
UserData userData = getUserData(demoForm);
//追加・更新処理
if(demoForm.getId() == null){
userData.setId(userDataDao.findMaxId() + 1);
userDataDao.create(userData);
}else{
userDataDao.update(userData);
}
}
/**
* {@inheritDoc}
*/
@Override
public String checkForm(DemoForm demoForm, BindingResult result, String normalPath){
//formオブジェクトのチェック処理を行う
if(result.hasErrors()){
//エラーがある場合は、入力画面のままとする
return "input";
}
//生年月日の日付チェック処理を行う
//エラーがある場合は、エラーメッセージ・エラーフィールドの設定を行い、
//入力画面のままとする
int checkDate = DateCheckUtil.checkDate(demoForm.getBirthYear()
, demoForm.getBirthMonth(), demoForm.getBirthDay());
switch(checkDate){
case 1:
//生年月日_年が空文字の場合のエラー処理
result.rejectValue("birthYear", "validation.date-empty"
, new String[]{"生年月日_年"}, "");
return "input";
case 2:
//生年月日_月が空文字の場合のエラー処理
result.rejectValue("birthMonth", "validation.date-empty"
, new String[]{"生年月日_月"}, "");
return "input";
case 3:
//生年月日_日が空文字の場合のエラー処理
result.rejectValue("birthDay", "validation.date-empty"
, new String[]{"生年月日_日"}, "");
return "input";
case 4:
//生年月日の日付が不正な場合のエラー処理
result.rejectValue("birthYear", "validation.date-invalidate");
//生年月日_月・生年月日_日は、エラーフィールドの設定を行い、
//メッセージを空文字に設定している
result.rejectValue("birthMonth", "validation.empty-msg");
result.rejectValue("birthDay", "validation.empty-msg");
return "input";
case 5:
//生年月日の日付が未来日の場合のエラー処理
result.rejectValue("birthYear", "validation.date-future");
//生年月日_月・生年月日_日は、エラーフィールドの設定を行い、
//メッセージを空文字に設定している
result.rejectValue("birthMonth", "validation.empty-msg");
result.rejectValue("birthDay", "validation.empty-msg");
return "input";
default:
//性別が不正に書き換えられていないかチェックする
if(!demoForm.getSexItems().keySet().contains(demoForm.getSex())){
result.rejectValue("sex", "validation.sex-invalidate");
return "input";
}
//エラーチェックに問題が無いので、正常時の画面遷移先に遷移
return normalPath;
}
}
/**
* DemoFormオブジェクトに引数のユーザーデータの各値を設定する
* @param userData ユーザーデータ
* @return DemoFormオブジェクト
*/
private DemoForm getDemoForm(UserData userData){
if(userData == null){
return null;
}
DemoForm demoForm = new DemoForm();
demoForm.setId(String.valueOf(userData.getId()));
demoForm.setName(userData.getName());
demoForm.setBirthYear(String.valueOf(userData.getBirthY()));
demoForm.setBirthMonth(String.valueOf(userData.getBirthM()));
demoForm.setBirthDay(String.valueOf(userData.getBirthD()));
demoForm.setSex(userData.getSex());
demoForm.setSex_value("1".equals(userData.getSex()) ? "男" : "女");
return demoForm;
}
/**
* UserDataオブジェクトに引数のフォームの各値を設定する
* @param demoForm DemoFormオブジェクト
* @return ユーザーデータ
*/
private UserData getUserData(DemoForm demoForm){
UserData userData = new UserData();
if(!DateCheckUtil.isEmpty(demoForm.getId())){
userData.setId(Long.valueOf(demoForm.getId()));
}
userData.setName(demoForm.getName());
userData.setBirthY(Integer.valueOf(demoForm.getBirthYear()));
userData.setBirthM(Integer.valueOf(demoForm.getBirthMonth()));
userData.setBirthD(Integer.valueOf(demoForm.getBirthDay()));
userData.setSex(demoForm.getSex());
return userData;
}
/**
* 引数の文字列をLong型に変換する
* @param id ID
* @return Long型のID
*/
private Long stringToLong(String id){
try{
return Long.parseLong(id);
}catch(NumberFormatException ex){
return null;
}
}
}
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.BindingResult; import java.util.ArrayList; import java.util.Collection; import java.util.List; @Service public class DemoServiceImpl implements DemoService{ /** * ユーザーデータテーブル(user_data)へアクセスするマッパー */ @Autowired private UserDataDao userDataDao; /** * {@inheritDoc} */ @Override public List<DemoForm> demoFormList() { List<DemoForm> demoFormList = new ArrayList<>(); //ユーザーデータテーブル(user_data)から全データを取得する Collection<UserData> userDataList = userDataDao.findAll(); for (UserData userData : userDataList) { demoFormList.add(getDemoForm(userData)); } return demoFormList; } /** * {@inheritDoc} */ @Override public DemoForm findById(String id) { Long longId = stringToLong(id); UserData userData = userDataDao.findById(longId); return getDemoForm(userData); } /** * {@inheritDoc} */ @Override @Transactional(readOnly = false) public void deleteById(String id){ UserData userData = new UserData(); userData.setId(stringToLong(id)); userDataDao.deleteById(userData); } /** * {@inheritDoc} */ @Override @Transactional(readOnly = false) public void createOrUpdate(DemoForm demoForm){ //更新・追加処理を行うエンティティを生成 UserData userData = getUserData(demoForm); //追加・更新処理 if(demoForm.getId() == null){ userData.setId(userDataDao.findMaxId() + 1); userDataDao.create(userData); }else{ userDataDao.update(userData); } } /** * {@inheritDoc} */ @Override public String checkForm(DemoForm demoForm, BindingResult result, String normalPath){ //formオブジェクトのチェック処理を行う if(result.hasErrors()){ //エラーがある場合は、入力画面のままとする return "input"; } //生年月日の日付チェック処理を行う //エラーがある場合は、エラーメッセージ・エラーフィールドの設定を行い、 //入力画面のままとする int checkDate = DateCheckUtil.checkDate(demoForm.getBirthYear() , demoForm.getBirthMonth(), demoForm.getBirthDay()); switch(checkDate){ case 1: //生年月日_年が空文字の場合のエラー処理 result.rejectValue("birthYear", "validation.date-empty" , new String[]{"生年月日_年"}, ""); return "input"; case 2: //生年月日_月が空文字の場合のエラー処理 result.rejectValue("birthMonth", "validation.date-empty" , new String[]{"生年月日_月"}, ""); return "input"; case 3: //生年月日_日が空文字の場合のエラー処理 result.rejectValue("birthDay", "validation.date-empty" , new String[]{"生年月日_日"}, ""); return "input"; case 4: //生年月日の日付が不正な場合のエラー処理 result.rejectValue("birthYear", "validation.date-invalidate"); //生年月日_月・生年月日_日は、エラーフィールドの設定を行い、 //メッセージを空文字に設定している result.rejectValue("birthMonth", "validation.empty-msg"); result.rejectValue("birthDay", "validation.empty-msg"); return "input"; case 5: //生年月日の日付が未来日の場合のエラー処理 result.rejectValue("birthYear", "validation.date-future"); //生年月日_月・生年月日_日は、エラーフィールドの設定を行い、 //メッセージを空文字に設定している result.rejectValue("birthMonth", "validation.empty-msg"); result.rejectValue("birthDay", "validation.empty-msg"); return "input"; default: //性別が不正に書き換えられていないかチェックする if(!demoForm.getSexItems().keySet().contains(demoForm.getSex())){ result.rejectValue("sex", "validation.sex-invalidate"); return "input"; } //エラーチェックに問題が無いので、正常時の画面遷移先に遷移 return normalPath; } } /** * DemoFormオブジェクトに引数のユーザーデータの各値を設定する * @param userData ユーザーデータ * @return DemoFormオブジェクト */ private DemoForm getDemoForm(UserData userData){ if(userData == null){ return null; } DemoForm demoForm = new DemoForm(); demoForm.setId(String.valueOf(userData.getId())); demoForm.setName(userData.getName()); demoForm.setBirthYear(String.valueOf(userData.getBirthY())); demoForm.setBirthMonth(String.valueOf(userData.getBirthM())); demoForm.setBirthDay(String.valueOf(userData.getBirthD())); demoForm.setSex(userData.getSex()); demoForm.setSex_value("1".equals(userData.getSex()) ? "男" : "女"); return demoForm; } /** * UserDataオブジェクトに引数のフォームの各値を設定する * @param demoForm DemoFormオブジェクト * @return ユーザーデータ */ private UserData getUserData(DemoForm demoForm){ UserData userData = new UserData(); if(!DateCheckUtil.isEmpty(demoForm.getId())){ userData.setId(Long.valueOf(demoForm.getId())); } userData.setName(demoForm.getName()); userData.setBirthY(Integer.valueOf(demoForm.getBirthYear())); userData.setBirthM(Integer.valueOf(demoForm.getBirthMonth())); userData.setBirthD(Integer.valueOf(demoForm.getBirthDay())); userData.setSex(demoForm.getSex()); return userData; } /** * 引数の文字列をLong型に変換する * @param id ID * @return Long型のID */ private Long stringToLong(String id){ try{ return Long.parseLong(id); }catch(NumberFormatException ex){ return null; } } }
package com.example.demo;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
 
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
 
@Service
public class DemoServiceImpl implements DemoService{
 
    /**
     * ユーザーデータテーブル(user_data)へアクセスするマッパー
     */
    @Autowired
    private UserDataDao userDataDao;
 
    /**
     * {@inheritDoc}
     */
    @Override
    public List<DemoForm> demoFormList() {
        List<DemoForm> demoFormList = new ArrayList<>();
        //ユーザーデータテーブル(user_data)から全データを取得する
        Collection<UserData> userDataList = userDataDao.findAll();
        for (UserData userData : userDataList) {
            demoFormList.add(getDemoForm(userData));
        }
        return demoFormList;
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public DemoForm findById(String id) {
        Long longId = stringToLong(id);
        UserData userData = userDataDao.findById(longId);
        return getDemoForm(userData);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional(readOnly = false)
    public void deleteById(String id){
        UserData userData = new UserData();
        userData.setId(stringToLong(id));
        userDataDao.deleteById(userData);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional(readOnly = false)
    public void createOrUpdate(DemoForm demoForm){
        //更新・追加処理を行うエンティティを生成
        UserData userData = getUserData(demoForm);
        //追加・更新処理
        if(demoForm.getId() == null){
            userData.setId(userDataDao.findMaxId() + 1);
            userDataDao.create(userData);
        }else{
            userDataDao.update(userData);
        }
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public String checkForm(DemoForm demoForm, BindingResult result, String normalPath){
        //formオブジェクトのチェック処理を行う
        if(result.hasErrors()){
            //エラーがある場合は、入力画面のままとする
            return "input";
        }
        //生年月日の日付チェック処理を行う
        //エラーがある場合は、エラーメッセージ・エラーフィールドの設定を行い、
        //入力画面のままとする
        int checkDate = DateCheckUtil.checkDate(demoForm.getBirthYear()
                , demoForm.getBirthMonth(), demoForm.getBirthDay());
        switch(checkDate){
            case 1:
                //生年月日_年が空文字の場合のエラー処理
                result.rejectValue("birthYear", "validation.date-empty"
                        , new String[]{"生年月日_年"}, "");
                return "input";
            case 2:
                //生年月日_月が空文字の場合のエラー処理
                result.rejectValue("birthMonth", "validation.date-empty"
                        , new String[]{"生年月日_月"}, "");
                return "input";
            case 3:
                //生年月日_日が空文字の場合のエラー処理
                result.rejectValue("birthDay", "validation.date-empty"
                        , new String[]{"生年月日_日"}, "");
                return "input";
            case 4:
                //生年月日の日付が不正な場合のエラー処理
                result.rejectValue("birthYear", "validation.date-invalidate");
                //生年月日_月・生年月日_日は、エラーフィールドの設定を行い、
                //メッセージを空文字に設定している
                result.rejectValue("birthMonth", "validation.empty-msg");
                result.rejectValue("birthDay", "validation.empty-msg");
                return "input";
            case 5:
                //生年月日の日付が未来日の場合のエラー処理
                result.rejectValue("birthYear", "validation.date-future");
                //生年月日_月・生年月日_日は、エラーフィールドの設定を行い、
                //メッセージを空文字に設定している
                result.rejectValue("birthMonth", "validation.empty-msg");
                result.rejectValue("birthDay", "validation.empty-msg");
                return "input";
            default:
                //性別が不正に書き換えられていないかチェックする
                if(!demoForm.getSexItems().keySet().contains(demoForm.getSex())){
                    result.rejectValue("sex", "validation.sex-invalidate");
                    return "input";
                }
                //エラーチェックに問題が無いので、正常時の画面遷移先に遷移
                return normalPath;
        }
    }
 
    /**
     * DemoFormオブジェクトに引数のユーザーデータの各値を設定する
     * @param userData ユーザーデータ
     * @return DemoFormオブジェクト
     */
    private DemoForm getDemoForm(UserData userData){
        if(userData == null){
            return null;
        }
        DemoForm demoForm = new DemoForm();
        demoForm.setId(String.valueOf(userData.getId()));
        demoForm.setName(userData.getName());
        demoForm.setBirthYear(String.valueOf(userData.getBirthY()));
        demoForm.setBirthMonth(String.valueOf(userData.getBirthM()));
        demoForm.setBirthDay(String.valueOf(userData.getBirthD()));
        demoForm.setSex(userData.getSex());
        demoForm.setSex_value("1".equals(userData.getSex()) ? "男" : "女");
        return demoForm;
    }
 
    /**
     * UserDataオブジェクトに引数のフォームの各値を設定する
     * @param demoForm DemoFormオブジェクト
     * @return ユーザーデータ
     */
    private UserData getUserData(DemoForm demoForm){
        UserData userData = new UserData();
        if(!DateCheckUtil.isEmpty(demoForm.getId())){
            userData.setId(Long.valueOf(demoForm.getId()));
        }
        userData.setName(demoForm.getName());
        userData.setBirthY(Integer.valueOf(demoForm.getBirthYear()));
        userData.setBirthM(Integer.valueOf(demoForm.getBirthMonth()));
        userData.setBirthD(Integer.valueOf(demoForm.getBirthDay()));
        userData.setSex(demoForm.getSex());
        return userData;
    }
 
    /**
     * 引数の文字列をLong型に変換する
     * @param id ID
     * @return Long型のID
     */
    private Long stringToLong(String id){
        try{
            return Long.parseLong(id);
        }catch(NumberFormatException ex){
            return null;
        }
    }
 
}

その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-doma/demo



「EaseUS Partition Master」はパーティション分割・結合・作成・サイズ変更等を直感的に行える便利ツールだったハードディスクの記憶領域を論理的に分割し、分割された個々の領域のことを、パーティションといいます。 例えば、以下の図の場合、C/D...

サンプルプログラムのビルド

サンプルプログラムをビルドするには、ビルド前にSQLファイルをクラスパスが通ったMETA-INFディレクトリ下に配置する必要がある。その手順は以下の通り。

1) IntelliJ IDEA上で右上「Gradle」タブをクリックし、Gradleタスクを表示する。
サンプルプログラムのビルド_1

2) buildタスクを選択し右クリックし、「demo[build]の作成」メニューを押下する。
サンプルプログラムのビルド_2

3) 以下の画面が開くため、起動前の「+」ボタンを押下し、「Gradleタスクの実行」メニューを選択する。
サンプルプログラムのビルド_3

4) build.gradleに設定したcopySqlタスクを設定し、「OK」ボタンを押下する。
サンプルプログラムのビルド_4

5) 起動前タスクにcopySqlタスクが設定されていることを確認後、「適用」ボタンを押下後、「OK」ボタンを押下する。
サンプルプログラムのビルド_5

6) buildタスクを選択し右クリックし、「実行」メニューを押下する。
サンプルプログラムのビルド_6

7) buildタスク実行時のコンソールログの内容は、以下の通り。
サンプルプログラムのビルド_7_1

サンプルプログラムのビルド_7_2

8) buildタスクによって、以下のビルド後ファイルが作成される。
サンプルプログラムのビルド_8_1

サンプルプログラムのビルド_8_2



サンプルプログラムの実行結果

Spring Bootアプリケーションを起動し、「http://(サーバー名):(ポート番号)/」とアクセスすると、以下の画面が表示される。
サンプルプログラムの実行結果_1

また、下記記事と同じように、データの追加・更新・削除を行うことができる。

Spring BootのWEB画面上でCRUDを含むOracleアクセス処理を実装してみた(完成イメージ編)今回は、C(Create)・R(Read)・U(Update)・D(Delete)を一通り含むOracle接続処理をSpring Boo...

さらに、プログラム実行時のSQLログの内容は、以下の通り。
サンプルプログラムの実行結果_2

要点まとめ

  • Domaとは、S2Daoのスタイル(DAOパターンや2 Way SQL)を踏襲したJava6(JDBC4.0)対応のO/Rマッパーで、Springフレームワークに組み込んで使うことができる。
  • Domaで実行するには、エンティティクラス、DAOインタフェース、SQLファイルが必要である。
  • SQLファイルは、DAOインタフェースにおいて、SELECT文またはsqlFile=trueであるDML文で必要になる。
  • SQLファイルは、「(クラスパスが通ったMETA-INFディレクトリ)/(実行するDaoのクラスパス)/(実行するDaoのメソッド名).sql」に記載する。