স্প্রিং ডাটা পার্শিয়াল অবজেক্ট আপডেট - স্প্রিং হাইবারনেট জেপিএ

databasehibernatepartialupdate

পার্শিয়াল আপডেট কি?


আপনি যদি স্প্রিং - হাইবারনেট জগতের বাসিন্দা হন, তাহলে জেনে থাকবেন যে, যখন আমরা রেপিজিটরিতে সেভ মেথড কল করি, সে তখন তাকে একটা আস্ত অবজেক্ট দেয়া লাগে। সে তখন পুরা অবজেক্টের উপর আপডেট চালায়।যদি আপনার অবজেক্ট ছোট হয় এবং বার বার আপডেট করার দরকার না হয়,তাহলে ঠিক আছে। কিন্ত অবজেক্ট যদি অনেক বড় হয় এবং আপনি সামান্য একটা ফিল্ড আপডেট করতে চাচ্ছেন তাহলে জিনিষটা একটু বেশিই হয়ে যায়।আবার আরো বেশি হয়ে যায় যখন অবজেক্টের কোন একটা ফিল্ড বারবার আপডেট করতে হয়।




বাস্তব উদাহরণ:


ব্লগের পোস্ট একটা বেশ বড় অবজেক্ট। আবার লেখক যখন পোস্ট লিখেন তখন তলে তলে একটা সময়ের ব্যবধানে পোস্ট বডি আপডেট করা উচিত। কেননা, কেউ এক ঘন্টা সময় ব্যয় করে একটা পোস্ট লিখে সাবমিট করার সময় কোন কারণে যদি পোস্ট সেভ না হয়, এর থেকে খারাপ ঘটনা আর হতে পারে না। তাহলে চলুন দেখা যাক marufh.com কিভাবে এই সমস্যার সমাধান করা হয়েছে।



ফ্রন্টএন্ড:


এঙ্গুলার কুইল এর মডেল পরিবর্তন কাউন্ট করার জন্য একটা কাউন্টার এবং কাউন্টারের মান একটা পর্যায়ের গেলেই আপডেট সার্ভিস কল হবে। আমার কাছে এটা বেশি এলিগেন্ট সুলুশন মনে হয়েছে।ধন্যবাদ সোহাগকে, এই নতুন বুদ্বি দেয়ার জন্য।


১. কুইলে এডিটরে মডেল চেঞ্জ মেথড ব্যবহার করা হয়েছে

<quill-editor
        (ngModelChange)="updateBody()"
        [(ngModel)]="post.body"
        [styles]="{height: '300px'}">
</quill-editor>  


২. কাউন্টার ২০ হলেই বডি আপডেট হয়ে যাবে

updateBody() {
  this.bodyCounter++;
  if ( this.post.id && this.bodyCounter === 20 ) {
    const data = new Post();
    data.id = this.post.id;
    data.body = this.post.body;
    this.adminPostService.partialUpdate(data)
        .subscribe( resp => {
          console.log('Body updated');
          this.bodyCounter = 0;
        });
  }
}


১. একটা rxjs এর interval চালু করে দিয়েছি প্রতি ৩০ সেকেন্ড পরপর

ngOnInit() {
  interval( 30000 ).subscribe( x => {
    this.updateBody();
  });

২. কিন্তু অন্ধভাবে ৩০ সেকেন্ড পরপর আপডেট করার মানে হয় না, লেখক চিন্তা করতে সময় নিতে পারে বা ইন্টারনেটে কোন কিছু সার্চ করতে পারে। তাই আগের এবং নতুন লেখার ক্যারেক্টার কাউন্ট করে সিদ্ধান্ত নেয়া হয়েছে।

updateBody() {
  if (this.post.id && this.post.body && this.post.body.length !== this.lastBodyLength) {
    const data = new Post();
    data.id = this.post.id;
    data.body = this.post.body;
    this.adminPostService.partialUpdate(data)
        .subscribe( resp => {
              console.log('Body updated');
              this.lastBodyLength = this.post.body.length;
        });
  }
}



৩. সার্ভিস

partialUpdate(post): Observable<any> {
  return this.http.put(ApiUrl.adminPosts  + 'partial-update/', post);
}



ব্যাকএন্ড:


আপনার অবজেক্টের বেশ করেকটা ফিল্ড থাকতে পারে, যাদেরকে আপনি পার্শিয়ালি আপডেট করতে চান। তাই সবচেয়ে ভালো হয়একটা DTO লিখে ফেললে। তারপর সার্ভিস থেকে আলাদা আলাদা রিপোজিটরি মেথড ব্যবহার করলেই হয়ে যাবে। কিন্তু একাধিক ফিলড থাকলে কোন ফিল্ড আপডেট করতেছি তার জন্য কন্ডিশন না লিখে জাভা ৮ এর অপশনাল এর চমৎকার ব্যবহার করা যায়।


১. পার্শিয়াল আপডেট এর জন্য DTO সাথে অপশনাল পাবলিক মেথড

@Data
public class PostPartialDto {

    @NotNull
    private String id;

    private String body;

    private Integer position;

    public Optional<String> body() {
        return Optional.ofNullable(body);
   }

    public Optional<Integer> position() {
        return Optional.ofNullable(position);
    }
}


২. সার্ভিস, এটার উপর আরো কাজ করতে হবে।

@Override
public Optional<Integer> partialUpdate(PostPartialDto postPartialDto) {
   
     postPartialDto.body()
            .map( body -> postRepository.updateBody(postPartialDto.getId(), body));

     postPartialDto.position()
             .map( position -> postRepository.updatePosition(postPartialDto.getId(), position));

     return Optional.of(1);
}



৩. সর্বশেষ স্প্রিং ডাটার পার্শিয়াল আপডেট কুয়েরি

@Modifying
@Transactional
@Query("update Post p set p.position = :position where p.id = :id")
Integer updatePosition(@Param("id") String id, @Param("position") Integer position);

@Modifying
@Transactional
@Query("update Post p set p.body = :body where p.id = :id")
Integer updateBody(@Param("id") String id, @Param("body") String body);


আমি এই পোস্ট যখন লিখছি তখনও সেটা ৩০ সেকেন্ড পরপর আপডেট হতে ছিল :) সবাইকে ঈদের শুভেচ্ছা, ঈদ মোবারক