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

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

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

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

Spring

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

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Spring Boot

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

Q&A

解決済

1回答

25638閲覧

DaoとRepositoryの使い方

sanezane

総合スコア91

Java

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

Spring

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

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Spring Boot

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

0グッド

1クリップ

投稿2019/02/16 15:48

Spring bootにてWebアプリ開発を勉強中です。Domaでのデータアクセスをしようと思った時に疑問が出たので質問します。

参考にしているプロジェクト内でDaoとRepositoryを分けているプロジェクトを見つけたため何が違うのかと調べていたのですが、イマイチ理解できないでいます。

参考にしているプロジェクト

その中でDaoとRepositoryを分けている箇所は以下のような実装をしています。

userdaojava

1package com.sample.domain.dao.users; 2 3import java.util.List; 4import java.util.Optional; 5import java.util.stream.Collector; 6 7import org.seasar.doma.*; 8import org.seasar.doma.boot.ConfigAutowireable; 9import org.seasar.doma.jdbc.SelectOptions; 10 11import com.sample.domain.dto.user.User; 12import com.sample.domain.dto.user.UserCriteria; 13 14@ConfigAutowireable 15@Dao 16public interface UserDao { 17 18 /** 19 * ユーザーを取得します。 20 * 21 * @param criteria 22 * @param options 23 * @return 24 */ 25 @Select(strategy = SelectType.COLLECT) 26 <R> R selectAll(final UserCriteria criteria, final SelectOptions options, final Collector<User, ?, R> collector); 27 28 /** 29 * ユーザーを1件取得します。 30 * 31 * @param id 32 * @return 33 */ 34 @Select 35 Optional<User> selectById(Long id); 36 37 /** 38 * ユーザーを1件取得します。 39 * 40 * @param criteria 41 * @return 42 */ 43 @Select 44 Optional<User> select(UserCriteria criteria); 45 46 /** 47 * ユーザーを登録します。 48 * 49 * @param user 50 * @return 51 */ 52 @Insert 53 int insert(User user); 54 55 /** 56 * ユーザーを更新します。 57 * 58 * @param user 59 * @return 60 */ 61 @Update 62 int update(User user); 63 64 /** 65 * ユーザーを論理削除します。 66 * 67 * @param user 68 * @return 69 */ 70 @Update(excludeNull = true) // NULLの項目は更新対象にしない 71 int delete(User user); 72 73 /** 74 * ユーザーを一括登録します。 75 * 76 * @param users 77 * @return 78 */ 79 @BatchInsert 80 int[] insert(List<User> users); 81 82 /** 83 * ユーザーを一括更新します。 84 * 85 * @param users 86 * @return 87 */ 88 @BatchUpdate 89 int[] update(List<User> users); 90} 91

UserRepository

1package com.sample.domain.repository.users; 2 3import static com.sample.domain.util.DomaUtils.createSelectOptions; 4import static java.util.Optional.ofNullable; 5import static java.util.stream.Collectors.toList; 6 7import java.util.Optional; 8 9import org.springframework.beans.factory.annotation.Autowired; 10import org.springframework.stereotype.Repository; 11 12import com.sample.domain.dao.system.UploadFileDao; 13import com.sample.domain.dao.users.UserDao; 14import com.sample.domain.dao.users.UserRoleDao; 15import com.sample.domain.dto.common.Page; 16import com.sample.domain.dto.common.Pageable; 17import com.sample.domain.dto.user.User; 18import com.sample.domain.dto.user.UserCriteria; 19import com.sample.domain.dto.user.UserRole; 20import com.sample.domain.exception.NoDataFoundException; 21import com.sample.domain.service.BaseRepository; 22 23import lombok.val; 24 25@Repository 26public class UserRepository extends BaseRepository { 27 28 @Autowired 29 UserDao userDao; 30 31 @Autowired 32 UserRoleDao userRoleDao; 33 34 @Autowired 35 UploadFileDao uploadFileDao; 36 37 /** 38 * ユーザーを取得します。 39 * 40 * @param criteria 41 * @param pageable 42 * @return 43 */ 44 public Page<User> findAll(UserCriteria criteria, Pageable pageable) { 45 // ページングを指定する 46 val options = createSelectOptions(pageable).count(); 47 val data = userDao.selectAll(criteria, options, toList()); 48 return pageFactory.create(data, pageable, options.getCount()); 49 } 50 51 /** 52 * ユーザーを取得します。 53 * 54 * @param criteria 55 * @return 56 */ 57 public Optional<User> findOne(UserCriteria criteria) { 58 // 1件取得 59 val user = userDao.select(criteria); 60 61 // 添付ファイルを取得する 62 user.ifPresent(u -> { 63 val uploadFileId = u.getUploadFileId(); 64 val uploadFile = ofNullable(uploadFileId).map(uploadFileDao::selectById); 65 uploadFile.ifPresent(u::setUploadFile); 66 }); 67 68 return user; 69 } 70 71 /** 72 * ユーザー取得します。 73 * 74 * @return 75 */ 76 public User findById(final Long id) { 77 return userDao.selectById(id).orElseThrow(() -> new NoDataFoundException("user_id=" + id + " のデータが見つかりません。")); 78 } 79 80 /** 81 * ユーザーを追加します。 82 * 83 * @param inputUser 84 * @return 85 */ 86 public User create(final User inputUser) { 87 88 // 1件登録 89 userDao.insert(inputUser); 90 91 // 役割権限紐付けを登録する 92 val userRole = new UserRole(); 93 userRole.setUserId(inputUser.getId()); 94 userRole.setRoleKey("users"); 95 userRoleDao.insert(userRole); 96 97 return inputUser; 98 } 99 100 /** 101 * ユーザーを更新します。 102 * 103 * @param inputUser 104 * @return 105 */ 106 public User update(final User inputUser) { 107 108 val uploadFile = inputUser.getUploadFile(); 109 if (uploadFile != null) { 110 // 添付ファイルがある場合は、登録・更新する 111 val uploadFileId = inputUser.getUploadFileId(); 112 if (uploadFileId == null) { 113 uploadFileDao.insert(uploadFile); 114 } else { 115 uploadFileDao.update(uploadFile); 116 } 117 118 inputUser.setUploadFileId(uploadFile.getId()); 119 } 120 121 // 1件更新 122 int updated = userDao.update(inputUser); 123 124 if (updated < 1) { 125 throw new NoDataFoundException("user_id=" + inputUser.getId() + " のデータが見つかりません。"); 126 } 127 128 return inputUser; 129 } 130 131 /** 132 * ユーザーを論理削除します。 133 * 134 * @return 135 */ 136 public User delete(final Long id) { 137 val user = userDao.selectById(id) 138 .orElseThrow(() -> new NoDataFoundException("user_id=" + id + " のデータが見つかりません。")); 139 140 int updated = userDao.delete(user); 141 142 if (updated < 1) { 143 throw new NoDataFoundException("user_id=" + id + " は更新できませんでした。"); 144 } 145 146 return user; 147 } 148} 149

このようにRepositoryにてDaoをAutoweredしてメソッドを使用しています。

私の中のDaoとRepository

私の中で2つは「デザインパターンレベルでのデータを取得したり、操作するもの」という認識で、大きな違いはないと理解していました。
ただ今回使い分けているんだからなんか違うんだろう、そして同じプロジェクトで同じ階層で使用すべきものなのだろうと思って調査をしました。

1.DaoとRepositoryのすみ分け

Repositoryはドメインオブジェクトを見て、DAOはデータ・ソースのマッピングするDTOの方を見る

「ベクトルが違うのはなんとなく伝わるけどまだわからない」
次!!!

2.リポジトリとDaoの住み分け方より

・リポジトリはドメインオブジェクトのコレクション ・DAOはデータアクセスのメカニズムを隠蔽する ・リポジトリの実装はドメインオブジェクトの構築です。

んー、頭の中で噛み砕けない。。。
恥ずかしながら私はデザインパターンを学んだ事がなく、こういう話は理解するのに苦労します。

SESの世界に例えた時に、簡単に言うと「二次請け企業と三次請け企業」のようにレイヤーが異なるという事でしょうか?
もう少し抽象的で構わないので子供に理解できるレベルの日本語で解説するとしたらどのような感じになりますでしょうか?
ご意見をよろしくお願いします。
また、皆さんの現場ではDaoとRepositoryは分けられていますか?

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

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

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

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

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

wwbQzhMkhhgEmhU

2019/02/17 03:35

ざっくり↓なイメージですが、特別両者を同じような位置付けで見たことがなかったです。 DAO=データベース周り Repository=それ以外 日本でリポジトリという言葉が使われ始めたのは、2000年くらいからだと思いますが、以来〇〇リポジトリでしっくり来る箱のときはリポジトリと呼んでる感じです。私が初めて知ったのはsvnを触ったときでした。ユーザーリポジトリはしっくり来る感じですし、Springでもそういうのあった気がします。 私はOO〜最近巡り巡って何故かまたDDDまでほとんど知らないので、使い方は適当ですけどね。
sanezane

2019/02/17 05:53

なるほど。私はSESで、開発案件としてまだ2件しか参画していませんでしたので、普通はどういう使い方をしているのか気になりました。 もう少しデザインパターンについて勉強したいと思います。
A-pZ

2019/02/18 19:15

回答は解答欄に入力しましょう
guest

回答1

0

ベストアンサー

SpringFrameworkが提案するRepositoryは、ドメイン駆動デザインのRepositoryとして用意され、JavaEEのDataAccessObject(DAO)と全く同じ扱いにもできますが、RepositoryはDAOよりも抽象度が高く、Repositoryを利用する側からは、どのデータストアに対して検索や更新しているかを意識せずに利用できるように設計・実装されるべき、とされています。

例えば何らかの検索機能を提供する際に、RDBから検索してした機能以外にも他のストレージやWebサービスへ切り替えるときに、これらを直接検索している処理はDAOで行わせ、DAOを切り替えることでRepositoryは常に期待する結果を返却するインタフェースを提供します。

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Repository.html

もちろん実際にDAOが扱うデータストアが単一の場合も多いでしょうから、Repository=DAOとしてしまうケースも多いでしょうし、DAOで利用するフレームワークを使うと、よりさらに違いがないと感じられる場面も多いでしょう。

アンチパターンも含めて、こちらに具体的な、砕けた例も書かれていますので参考になれば幸いです。

https://qiita.com/mikesorae/items/ff8192fb9cf106262dbf

投稿2019/02/18 19:43

A-pZ

総合スコア12011

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

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

sanezane

2019/03/05 15:04

Repositoryは永続化する機能に絞って複雑な条件の処理はServiceで実装する。 アンチパターンに気をつけて過ごします。 Qiitaの記事わかりやすかったです。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問