جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی


در برخی موارد خاص نیاز داریم که نتایج کوئری ها را بصورت سفارشی و دلخواه داشته باشیم مانند وقتی که از توابع Aggregation استفاده میکنیم در این بخش خواهیم دید که چگونه میتوان نتایج این نوع از کوئری ها در  دو نوع ابجکت POJO و Spring Data Projection دریافت کنیم 



مشکل کوئری های JPA و توابع Aggregation :


نتایج کوئری های JPA معمولا روی یک Entity متناظر میشوند و نتایج کوئری های Aggregation بصورت []Object هستند 

برای فهم این مشکل بزارید Domain Model خود را بر اساس رابطه Post و Comment که قبلا بحث شده بود پیاده سازی کنیم :

@Entity
public class Post {
    @Id
    private Integer id;
    private String title;
    private String content;
    @OneToMany(mappedBy = "post")
    private List comments;
 
    // additional properties
    // standard constructors, getters, and setters
}
@Entity
public class Comment {
    @Id
    private Integer id;
    private Integer year;
    private boolean approved;
    private String content;
    @ManyToOne
    private Post post;
 
    // additional properties
    // standard constructors, getters, and setters
}


هر Post میتواند تعدادی Comment داشته باشد و هر Comment متعلق به یک Post است 



Repository را شکل میدهیم :


@Repository
public interface CommentRepository extends JpaRepository<Comment, Integer> {
    // query methods
}

و یک متد در آن برای گرفتن تعداد Comment ها بر اساس سال مینویسیم :


@Query("SELECT c.year, COUNT(c.year) FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC")
List<Object[]> countTotalCommentsByYear();


نتیجه این کوئری نمیتواند در Comment جای بگیرید چون نتیجه آن که شامل year و COUNT است متفاوت از ساختار Comment است و از طرفی دریافت نتایج در قالب []Object میتواند کد ما را مستعد خطا کند 


پس راه حل چیست ؟ 


ست کردن نتیجه کوئری در ابجکت سفارشی :


ویژگی JPA به ما این اجازه را میدهد که نتایج را در قالب Object دلخواه ست کنیم و با استفاده از JPQL نتیجه را دریافت کنیم :


@Query("SELECT new com.baeldung.aggregation.model.custom.CommentCount(c.year, COUNT(c.year)) "
  + "FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC")
List<CommentCount> countTotalCommentsByYearClass();


خروجی این کوئری روی یک ابجکت Bind شده است که این کلاس باید Constructor ی داشته باشد که دقیقا مطابق با Attribute های خروجی کوئری باشد و در JPQL از آن استفاده شده باشد که قابل مشاهد است . این کلاس نیازی ندارد که یک Entity@ باشد 


package com.baeldung.aggregation.model.custom;
 
public class CommentCount {
    private Integer year;
    private Long total;
 
    public CommentCount(Integer year, Long total) {
        this.year = year;
        this.total = total;
    }
    // getters and setters
}





نتیجه کوئری را نیز میتوان بصورت Spring Projection تبدیل و دریافت کرد :


این روش کدنویسی کمتری نیاز دارد. 

ابتدا یک اینترفیس طراحی میکنیم که دارای متد های getter مطابق با Attribute ها مطابقت داشته باشد :

public interface ICommentCount {
    Integer getYearComment();
    Long getTotalComment();
}


حالا کوئری آنرا مینویسیم که مقدار برگشتی آن List ای از ICommentCount است :


@Query("SELECT c.year AS yearComment, COUNT(c.year) AS totalComment "
  + "FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC")
List<ICommentCount> countTotalCommentsByYearInterface();


* برای آنکه Spring بتواند اینترفیس را با استفاده از پروکسی پیاده سازی کند و مقادیر را به فیلد های متناظر آن وارد کند باید از Alias در کوئری خود استفاده کنیم که با نام فیلد ها مطابقت داشته باشد که در بالا قابل مشاهده است 




همانطور که میدانیم کوئری های JPA همانند Native سریع نیستند و از اینترفیس ICommentCount که طراحی کردیم میتوانیم برای Native Query هم استفاده کنیم :


@Query(value = "SELECT c.year AS yearComment, COUNT(c.*) AS totalComment "
  + "FROM comment AS c GROUP BY c.year ORDER BY c.year DESC", nativeQuery = true)
List<ICommentCount> countTotalCommentsByYearNative();


همانند JPQL خروجی را دریافت خواهد کرد 











نظرات  (۰)

هیچ نظری هنوز ثبت نشده است

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی