DAO



チェスゲームを通じて、DAOオブジェクトのDB接続を初めて体験しました.DAO의 개념DB 접근을 DAO로 분리하는 이유について説明しましょう.

DAOとは?


次に示すように、データベースに値(データ・アクセス・オブジェクト)を格納し、データベースから値を取り出してコントローラまたはサービス・オブジェクトに渡す役割を果たします.
public class PieceDao {

    public void savePiece(final Position position, final Piece piece) {
        final String sql = "insert into piece (position, team, name) values (?, ?, ?)";

        try (final PreparedStatement statement = getConnection().prepareStatement(sql)) {
            statement.setString(1, position.toString());
            statement.setString(2, piece.getTeam());
            statement.setString(3, position.getName());
			statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

なぜDBアクセス責任をDAOに分割するのか


1.責任分離


オブジェクト向けの例では、共通のターゲットの機能を複数の責任に分割し、責任を複数のオブジェクトに分割します.分離の責任では、DAOがデータベース接続を担当します.
データベースに複数のテーブルがある場合は、1つのテーブルにアクセスする責任をオブジェクトに付与できます.

2.変化に柔軟に対応(拡張可能)


使用するデータがOracleデータベースにアクセスするとします.
public class PieceDaoOracle {

    public void savePiece(final Position position, final Piece piece) {

	}
}
その後、データベースがMySQLに変更された場合、どうすればいいですか?
データベース・アクセス責任をDAOに分離し、次のインタフェースを使用して変更に応答します.
public interface PieceDao {
    void savePiece(final Position position, final Piece piece);
}
PieceDaoインタフェースを使用して抽象化し、必要に応じて以下の実装を置き換えることができます.
public class PieceDaoOracle implements PieceDao {

	@Override
    public void savePiece(final Position position, final Piece piece) {
					//Oracle DB Connection
	}
}
public class PieceDaoMySQL implements PieceDao {

	@Override
    public void savePiece(final Position position, final Piece piece) {
					//MySQL DB Connection
	}
}
ただし、DAOの役割を分離するのではなく、サービス・オブジェクトに次のような内容を持たせます.
サービス・オブジェクトをインタフェースに分離し、データベース・タイプに基づいてサービス・インプリメンテーション・オブジェクトを作成する必要があります.
public interface ChessGameService {
    void movePiece(final Position source, final Position target);
}
public interface ChessGameServiceMySQL {
		
	@Override
    public void movePiece(final Position source, final Position target) {
				//MySQL DB로 이뤄지는 Service 로직
	}
}
public interface ChessGameServiceOracle {
		
	@Override
    public void movePiece(final Position source, final Position target) {
				//Oracle DB로 이뤄지는 Service 로직
	}
}

3.テストしやすい


サービス・オブジェクトでサービス・ロジックのテストを作成することを考慮します.
サービスの論理はDAOを介してDBにアクセスすることである.
そうであれば、テスト中のデータがデータベースを汚染します.
この場合、データベース・アクセスをDAOに分離し、DAOをサービス・オブジェクトに注入することで問題を解決できます.
1.データベースにアクセスしてテストするDAO
テスト・データベースを作成し、データベースにアクセスしたDAOをサービス・オブジェクトに注入します.
テスト中、生産データベースは汚染されません.
public class ChessGameService {
		
	private final PieceDao pieceDao;

	public ChessGameService(final PieceDao pieceDao) {
			this.pieceDao = pieceDao;
	}

    void movePiece(final Position source, final Position target) {
    
    }
}
class ChessGameSerciceTest {
		private final ChessGameService chessGameService = 
        							new ChessGameService(new PieceDaoFake);

}
public class PieceDaoTestDB implements PieceDao {
			//프로덕션 DB가 아닌 Test를 위한 DB에 Connection
}
2.DBのように表現されたダミーを注入する
データベースが実際に接続されている場合は、サービス・オブジェクトをテストします.
テスト中にデータベースへの接続とアクセスが必要になるため、テストのパフォーマンスが低下します.
サービステストでは、データベースが実際に接続されているかどうかは重要ではありません.
サービスロジックが正常に動作しているかどうかを確認するだけです.
したがって、DB接続のないDAOをサービス・オブジェクトに注入する場合は、次の操作を行います.
サービス・オブジェクトのテスト・パフォーマンスを向上させます.
public class ChessGameService {
		
	private final PieceDao pieceDao;

	public ChessGameService(final PieceDao pieceDao) {
			this.pieceDao = pieceDao;
	}

    void movePiece(final Position source, final Position target) {
    
    }
}
class ChessGameSerciceTest {

		private final ChessGameService chessGameService = 
        							new ChessGameService(new PieceDaoFake);

}
public class PieceDaoFake implements PieceDao {

		private final Map<String, Piece> fakeDB = new HashMap<>();
}
PieceDaoFakeオブジェクトのfakeDBフィールドは、DBの役割を置き換えることができます.
サービス・オブジェクトのテスト中に、実際にはデータベース接続はありません.
生産データベースは汚染されず、テスト性能が向上する可能性があります.


ある面白いジョークでこの文章を終わらせる
ソース:https://okky.kr/article/153941