جلسه شماره 133رایگان

Reading Data with JdbcTemplate | خواندن داده با JdbcTemplate

00:30:53

توضیحات جلسه

🎥 این ویدیو قسمت صد و هفدهم از بوت‌کمپ رایگان جاوا و شانزدهمین جلسه از پلی‌لیست تخصصی آموزش فریم‌ورک اسپرینگ است. 📚 در این جلسه به سراغ یکی از مفاهیم کلیدی در معماری نرم‌افزار می‌رویم: پیاده‌سازی لایه دسترسی به داده با استفاده از الگوی Repository و ابزار قدرتمند JdbcTemplate. در این ویدیو به طور کامل بررسی می‌کنیم که چگونه می‌توانیم عملیات خواندن داده (Read) را از دیتابیس به صورت تمیز و ساختاریافته انجام دهیم. به جای نوشتن کدهای پراکنده در سراسر برنامه، یاد می‌گیریم که چطور یک JDBC Repository اختصاصی برای موجودیت‌های خود تعریف کنیم. در نهایت نیز این ریپازیتوری را در پروژه اصلی تاکو (Taco Cloud) فراخوانی می‌کنیم تا داده‌ها را از دیتابیس دریافت کرده و در لایه‌های بالاتر برنامه استفاده کنیم. در این جلسه یاد می‌گیریم: ⚙️ تعریف و ساختار یک JDBC Repository در اسپرینگ 🛠️ پیاده‌سازی متدهای خواندن داده با استفاده از JdbcTemplate 🧩 نحوه تزریق و استفاده از Repository در لایه‌های مختلف برنامه 🧠 در پایان نیز یک جمع‌بندی کامل از مباحث مطرح‌شده در این جلسه خواهیم داشت اگر در حال یادگیری Spring Boot هستید، درک الگوی Repository یکی از مهم‌ترین مهارت‌هایی است که به شما کمک می‌کند کدی تمیز، تست‌پذیر و قابل نگهداری بنویسید. 📌 یوتیوب: https://youtube.com/@farzadafi 📌 آپارت: https://aparat.com/farzadafi 📌 وب سایت: https://farzadafi.ir 📌 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi وب سایت: https://farzadafi.ir هر سوالی داشته باشید می‌توانید در گروه بپرسید تا من یا مربی‌های گروه کمکتان کنیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش کاملاً پروژه‌محور برای یادگیری عمیق جاوا و ورود به بازار کار.

جزوه و مستندات

مفاهیم کلیدی

  • @Repository

یک Stereotype Annotation در فریم‌ورک اسپرینگ که کلاس‌های لایه دسترسی به داده (Data Access Layer) را مشخص می‌کند؛ این انوتیشن علاوه بر شناسایی خودکار کلاس در فرآیند Component Scanning، خطاهای پایگاه داده را به صورت خودکار به سلسله‌مراتب DataAccessException تبدیل می‌نماید.

  • Constructor Injection

رویکرد استاندارد و توصیه‌شده جهت تزریق وابستگی‌ها در اسپرینگ؛ چنانچه یک کلاس تنها دارای یک Constructor باشد، اسپرینگ به صورت خودکار و بدون نیاز به نوشتن صریح انوتیشن @Autowired، وابستگی‌های ورودی سازنده را تزریق می‌کند.

  • JdbcTemplate.query()

متدی در کلاس JdbcTemplate جهت اجرای کوئری‌های خواندن از پایگاه داده که دستور SQL، یک پیاده‌سازی از RowMapper و پارامترهای اختیاری کوئری را دریافت کرده و فهرستی از اشیاء نگاشت‌شده را بازمی‌گرداند.

  • RowMapper

یک اینترفیس تابعی (Functional Interface) در اسپرینگ که نحوه تبدیل هر سطر از شیء ResultSet را به یک نمونه مشخص از اشیاء دامنه تعیین می‌کند.

  • Method Reference

قابلیتی در جاوا (به فرمت ClassName::methodName) که اجازه می‌دهد یک متد موجود را به صورت مستقیم به عنوان پیاده‌سازی اینترفیس تابعی مانند RowMapper به متد query() پاس داد و کدهای ساختاری تکراری را حذف کرد.

  • Parameterized Query

تکنیک ارسال پارامترها به دستور SQL با استفاده از عملگر جایگزینی ? در JdbcTemplate که علاوه بر جلوگیری از حملات SQL Injection، مدیریت انواع داده‌ها را به درایور پایگاه داده محول می‌سازد.

موارد مصاحبه ای

  • تفاوت @Repository با @Component چیست؟

هر دو انوتیشن باعث تعریف شیء به عنوان یک Bean در کانتکست اسپرینگ می‌شوند، اما @Repository به طور خاص برای لایه دسترسی به داده‌ها در نظر گرفته شده و قابلیت ترجمه خودکار خطاهای دیتابیس (Exception Translation) را فراهم می‌آورد.

  • چرا در کلاس‌هایی با یک Constructor نیازی به قرار دادن انوتیشن @Autowired نیست؟

اگر کلاسی تنها یک سازنده داشته باشد، اسپرینگ به طور ضمنی (Implicitly) آن را به عنوان نقطه تزریق وابستگی در نظر می‌گیرد و نیازی به تعریف صریح @Autowired وجود ندارد.

  • چگونه می‌توان متد RowMapper را با روش‌های نوین جاوا خلاصه کرد؟

به دلیل اینکه RowMapper یک اینترفیس تابعی با متد تک‌امضایی mapRow است، می‌توان آن را با عبارات لامبدا (Lambda Expressions) یا ارجاع به متد (Method Reference) مانند this::mapRowToIngredient جایگزین نمود و از ایجاد کلاس‌های بی‌نام خودداری کرد.

  • نحوه انتقال پارامترهای پویا به کوئری‌ها در متد query() چگونه است؟

پارامترها به صورت آرگومان متغیر (Varargs) پس از تعریف RowMapper به متد query() ارسال می‌شوند و بر اساس ترتیب قرارگیری، جایگزین علامت‌های ? در دستور SQL خواهند شد.

سناریو کاربردی

  • پیاده‌سازی لایه دسترسی به داده برای واکشی اقلام بر اساس شناسه و واکشی تمام داده‌ها

در این سناریو، اینترفیس مخزن با استفاده از JdbcTemplate پیاده‌سازی شده و از ارجاع به متد برای نگاشت داده‌های ResultSet استفاده می‌شود:

@Repository
public class JdbcIngredientRepository implements IngredientRepository {

    private final JdbcTemplate jdbcTemplate;

    public JdbcIngredientRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public Iterable<Ingredient> findAll() {
        return jdbcTemplate.query(
            "select id, name, type from Ingredient",
            this::mapRowToIngredient
        );
    }

    @Override
    public Optional<Ingredient> findById(String id) {
        List<Ingredient> results = jdbcTemplate.query(
            "select id, name, type from Ingredient where id = ?",
            this::mapRowToIngredient,
            id
        );

        return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0));
    }

    private Ingredient mapRowToIngredient(ResultSet row, int rowNum) throws SQLException {
        return new Ingredient(
            row.getString("id"),
            row.getString("name"),
            Ingredient.Type.valueOf(row.getString("type"))
        );
    }
}

بیشتر بدانید

  • تزریق صریح وابستگی در کلاس‌های چندسازنده‌ای

چنانچه در یک کلاس بیش از یک Constructor تعریف شده باشد، کانتکست اسپرینگ نمی‌تواند سازنده هدف را تشخیص دهد؛ بنابراین در این شرایط استفاده از انوتیشن @Autowired بر روی سازنده اصلی الزامی است.

  • استفاده از Lombok برای تزریق وابستگی تمیز

به جای تعریف دستی سازنده جهت تزریق وابستگی JdbcTemplate، می‌توان از انوتیشن @RequiredArgsConstructor کتابخانه Lombok روی سطح کلاس استفاده کرد و متغیر jdbcTemplate را به صورت private final تعریف نمود تا کدهای تکراری سازنده حذف شوند.