জেপিএ সিঙ্গল রিসাল্ট () বা নাল পায়


136

আমার কাছে এমন একটি insertOrUpdateপদ্ধতি রয়েছে যা Entityএটি উপস্থিত না থাকলে একটি সন্নিবেশ করায় বা তা থাকলে আপডেট করে। এটি সক্ষম করতে, আমাকে করতে হবে findByIdAndForeignKey, যদি এটি nullসন্নিবেশ ফিরিয়ে দেয় তবে আপডেট হয় না। সমস্যাটি হ'ল এটি উপস্থিত আছে কিনা তা আমি কীভাবে পরীক্ষা করব? তাই চেষ্টা করেছি getSingleResult। তবে এটি ব্যতিক্রম ছুঁড়ে যদি

public Profile findByUserNameAndPropertyName(String userName, String propertyName) {
    String namedQuery = Profile.class.getSimpleName() + ".findByUserNameAndPropertyName";
    Query query = entityManager.createNamedQuery(namedQuery);
    query.setParameter("name", userName);
    query.setParameter("propName", propertyName);
    Object result = query.getSingleResult();
    if (result == null) return null;
    return (Profile) result;
}

কিন্তু getSingleResultএকটি ছুড়ে Exception

ধন্যবাদ

উত্তর:


266

একটি ব্যতিক্রম ছুঁড়ে ফেলা হচ্ছে getSingleResult()এটি কীভাবে খুঁজে পাওয়া যায় তা নির্দেশ করে। ব্যক্তিগতভাবে আমি এই জাতীয় এপিআই দাঁড়াতে পারি না। এটি আসল উপকারের জন্য জালিয়াতি ব্যতিক্রম পরিচালনা করার জন্য জোর করে। আপনাকে কেবল একটি চেষ্টা-ধরার ব্লকে কোডটি মোড়াতে হবে।

বিকল্পভাবে আপনি একটি তালিকার জন্য জিজ্ঞাসা করতে পারেন এবং খালি কিনা তা দেখতে পারেন। এটি একটি ব্যতিক্রম ছুঁড়ে না। প্রকৃতপক্ষে আপনি প্রযুক্তিগতভাবে কোনও প্রাথমিক কী অনুসন্ধান করছেন না এমন একাধিক ফলাফল হতে পারে (যদিও উভয়ই বা আপনার বিদেশী কী বা সীমাবদ্ধতার সংমিশ্রণটি বাস্তবে এটি অসম্ভব করে তোলে) তাই সম্ভবত এটিই আরও উপযুক্ত সমাধান।


115
আমি একমত নই, getSingleResult()এমন পরিস্থিতিতে ব্যবহার করা হয়: " আমি পুরোপুরি নিশ্চিত যে এই রেকর্ডটি বিদ্যমান আছে। যদি তা না হয় তবে আমাকে গুলি করুন "। আমি nullযখনই এই পদ্ধতিটি ব্যবহার করি ততবারের জন্য আমি পরীক্ষা করতে চাই না কারণ আমি নিশ্চিত যে এটি এটি ফেরত দেবে না। অন্যথায় এটি প্রচুর বয়লারপ্লেট এবং রক্ষণাত্মক প্রোগ্রামিংয়ের কারণ হয়ে থাকে। এবং যদি রেকর্ডটি সত্যই উপস্থিত না থাকে (আমরা যা অনুমান করেছি তার বিপরীতে), পরে কয়েকটি লাইনের NoResultExceptionসাথে তুলনা করা আরও ভাল NullPointerException। অবশ্যই দুটি সংস্করণ getSingleResult()থাকা দুর্দান্ত হবে তবে আমার যদি
একটিটি

8
@ ক্লেটাস নুল একটি ডাটাবেসের জন্য সত্যই একটি বৈধ রিটার্ন মান।
বিল রোসমাস

12
@ টমাস নুরকিউইজ এটি একটি ভাল পয়েন্ট। তবে মনে হয় কিছুটা "getSingleResultOrNull" হওয়া উচিত। আমার ধারণা আপনি এরকম একটি মোড়ক তৈরি করতে পারেন।
cbmeeks

2
GetSingleResult () থেকে ব্যতিক্রম হওয়া সুবিধার মেয়াদে কিছু তথ্য এখানে দেওয়া হয়েছে: একক সারিতে একক কলামের মান সহ প্রায় কোনও কিছু উদ্ধার করতে কোয়েরিগুলি ব্যবহার করা যেতে পারে। যদি getSingleResult () বাতিল হয়ে যায়, আপনি জিজ্ঞাসাটি কোনও সারির সাথে মেলে না বা কোয়েরিটি একটি সারির সাথে মেলে কিনা তা আপনি বলতে পারেন নি তবে নির্বাচিত কলামটিতে এর মান হিসাবে নাল রয়েছে। থেকে: স্ট্যাকওভারফ্লো.com / a / 12155901 / 1242321
user1242321

5
এটি returnচ্ছিক ফিরে আসতে হবে <T>। অনুপস্থিত মানগুলি নির্দেশ করার জন্য এটি একটি ভাল উপায়।
বিবেক কোঠারি

33

আমি নিম্নলিখিত সহায়ক পদ্ধতিতে যুক্তিটি encapsulated।

public class JpaResultHelper {
    public static Object getSingleResultOrNull(Query query){
        List results = query.getResultList();
        if (results.isEmpty()) return null;
        else if (results.size() == 1) return results.get(0);
        throw new NonUniqueResultException();
    }
}

2
নোট করুন যে আপনি Query.setMaxResults (1) কল করে কিছুটা অনুকূল হতে পারবেন। দুঃখের বিষয়, যেহেতু ক্যোয়ারি স্থিতিযুক্ত, আপনি কোয়েরি.বেটম্যাক্স রেসাল্টস () এর মান ক্যাপচার করতে এবং অবজেক্টটিকে একটি চূড়ান্ত অবরুদ্ধের মধ্যে ঠিক করতে চাইবেন এবং যদি ক্যোরি.জিটফার্সআরস্টল্ট () আকর্ষণীয় কিছু ফেরত দেয় তবে পুরোপুরি ব্যর্থ হতে পারে।
প্যাট্রিক লিনস্কি

আমরা আমাদের প্রকল্পে এটি বাস্তবায়ন করেছি। এই বাস্তবায়ন নিয়ে কখনও কোনও সমস্যা
হয়নি


24

এটি করার জন্য এখানে একটি ভাল বিকল্প:

public static <T> T getSingleResult(TypedQuery<T> query) {
    query.setMaxResults(1);
    List<T> list = query.getResultList();
    if (list == null || list.isEmpty()) {
        return null;
    }

    return list.get(0);
}

2
ঝরঝরে! TypedQuery<T>যদিও আমি গ্রহণ করব , সেক্ষেত্রে ক্ষেত্রে getResultList()ইতিমধ্যে সঠিকভাবে টাইপ করা হয়েছে List<T>
রুপ

fetch()সত্তার সাথে সংমিশ্রণে সম্পূর্ণরূপে পপুলেট করা যায় না। দেখুন stackoverflow.com/a/39235828/661414
Leukipp

1
এটি একটি খুব সুন্দর পদ্ধতির। নোট করুন যে setMaxResults()একটি সাবলীল ইন্টারফেস আছে যাতে আপনি লিখতে পারেন query.setMaxResults(1).getResultList().stream().findFirst().orElse(null)। এটি জাভা 8+ এর মধ্যে সবচেয়ে দক্ষ কল স্কিম হওয়া উচিত।
ডার্ক হিলব্রেক্ট


15

আমি করেছি (জাভা 8 এ):

query.getResultList().stream().findFirst().orElse(null);

আপনি জিজ্ঞাসা বলতে কি বোঝাতে চান?
এনরিকো গিউরিন

আপনি হাইবারনেটকুয়েরি মানে? আমি যদি খাঁটি জেপিএ এপিআই ব্যবহার করতে চাই তবে কী হবে? জাভ্যাক্স.পার্সটিশন.কিউয়েরিতে এমন কোনও পদ্ধতি নেই
এনরিকো গিউরিন

2
@ ইরিকো জিউরিন, আমি স্নিপেট সম্পাদনা করেছি। ভাল কাজ। কোন চেষ্টা-ধরা, এবং কোন list.size চেক। নিকৃষ্ট ওয়ান লাইনারের দ্রবণ।
লোভাবিলে

10

জেপিএ ২.২ থেকে পরিবর্তে .getResultList()এবং তালিকা খালি কিনা তা পরীক্ষা করে নেওয়া বা একটি স্ট্রিম তৈরি করে আপনি স্রোতে ফিরে আসতে পারেন এবং প্রথম উপাদানটি নিতে পারেন।

.getResultStream()
.findFirst()
.orElse(null);

7

যদি আপনি এই সমস্যাটি পরিচালনা করতে চেষ্টা / ধরার ব্যবস্থাটি ব্যবহার করতে চান তবে .. / অন্যটি যদি এটির মতো কাজ করতে ব্যবহৃত হয়। যখন আমি কোন বিদ্যমান খুঁজে পেলাম না তখনই আমি নতুন রেকর্ড যুক্ত করার চেষ্টা / ধরাকে ব্যবহার করেছি।

try {  //if part

    record = query.getSingleResult();   
    //use the record from the fetched result.
}
catch(NoResultException e){ //else part
    //create a new record.
    record = new Record();
    //.........
    entityManager.persist(record); 
}

6

রডরিগো আয়রনম্যান এর প্রয়োগের উপর ভিত্তি করে এখানে একটি টাইপ করা / জেনেরিক সংস্করণ রয়েছে:

 public static <T> T getSingleResultOrNull(TypedQuery<T> query) {
    query.setMaxResults(1);
    List<T> list = query.getResultList();
    if (list.isEmpty()) {
        return null;
    }
    return list.get(0);
}

5

একটি বিকল্প আছে যা আমি সুপারিশ করব:

Query query = em.createQuery("your query");
List<Element> elementList = query.getResultList();
return CollectionUtils.isEmpty(elementList ) ? null : elementList.get(0);

নুল পয়েন্টার ব্যতিক্রমের বিরুদ্ধে এই সুরক্ষাগুলি, কেবলমাত্র 1 টি ফলাফল প্রত্যাবর্তনের গ্যারান্টি দেয়।


4

সুতরাং যে না!

আপনার দুটি বিকল্প রয়েছে:

  1. আপনার ফলাফলের সেটটির COUNT টি পেতে একটি নির্বাচন চালান এবং কেবল এই ডেটাটি টানুন যদি এই গণনাটি শূন্য নয়; অথবা

  2. অন্যান্য ধরণের ক্যোয়ারী ব্যবহার করুন (এটি একটি ফলাফল সেট পায়) এবং এটিতে 0 বা তার বেশি ফলাফল রয়েছে কিনা তা পরীক্ষা করে দেখুন। এটির 1 টি হওয়া উচিত, সুতরাং এটি আপনার ফলাফল সংগ্রহের বাইরে টানুন এবং আপনার কাজ শেষ।

আমি ক্লিটাসের সাথে চুক্তিতে দ্বিতীয় পরামর্শ নিয়ে যাব। এটি (সম্ভাব্য) 2 টি প্রশ্নের চেয়ে আরও ভাল পারফরম্যান্স দেয়। কাজও কম।


1
বিকল্প 3 চেষ্টা করুন / NoResultException ধরার জন্য
সিড

3

বিদ্যমান উত্তরের দরকারী বিটের সংমিশ্রণ (ফলাফলের সংখ্যা সীমাবদ্ধ করে, ফলাফলটি অনন্য checking

/**
 * Return a single instance that matches the query, or null if the query returns no results.
 *
 * @param query query (required)
 * @param <T> result record type
 * @return record or null
 */
public static <T> T uniqueResult(@NotNull TypedQuery<T> query) {
    List<T> results = query.setMaxResults(2).getResultList();
    if (results.size() > 1) throw new NonUniqueResultException();
    return results.isEmpty() ? null : results.get(0);
}

3

uniqueResultOptionalOrg.hibernate.query.Query এ নথিভুক্ত পদ্ধতিটি কৌশলটি করা উচিত। একটি ধরার পরিবর্তে NoResultExceptionআপনি কেবল কল করতে পারেন query.uniqueResultOptional().orElse(null)


2

আমি এটি ব্যবহার করে শূন্যের সমান List<?> myList = query.getResultList();কিনা তা পরীক্ষা করে সমাধান করেছি myList.size()


1

গুগল পেয়ারা এবং একটি টাইপকিউরি ব্যবহার করে অন্যরা যেমন প্রস্তাব করেছে (ফলাফলের তালিকাটি পান, তার একমাত্র উপাদানটি বাতিল বা নাল ফেরান) এখানে একই যুক্তি's

public static <T> getSingleResultOrNull(final TypedQuery<T> query) {
    return Iterables.getOnlyElement(query.getResultList(), null); 
}

দ্রষ্টব্য যে পেয়ারা যদি ফলাফলের সেটগুলির একাধিক ফলাফল থাকে তবে অযৌক্তিক অবৈধ আইন-অনুগ্রহ ফিরিয়ে দেবে। (ব্যতিক্রমটি getOnEEELEM () এর ক্লায়েন্টদের কাছে বোধগম্য হয়, কারণ এটি ফলাফলের তালিকাটিকে তার যুক্তি হিসাবে গ্রহণ করে তবে getSingleResultOrNull () এর ক্লায়েন্টদের কাছে কম বোধগম্য))


1

এখানে আরও একটি বর্ধিতাংশ, এবার স্কালায়।

customerQuery.getSingleOrNone match {
  case Some(c) => // ...
  case None    => // ...
}

এই পিম্প সহ:

import javax.persistence.{NonUniqueResultException, TypedQuery}
import scala.collection.JavaConversions._

object Implicits {

  class RichTypedQuery[T](q: TypedQuery[T]) {

    def getSingleOrNone : Option[T] = {

      val results = q.setMaxResults(2).getResultList

      if (results.isEmpty)
        None
      else if (results.size == 1)
        Some(results.head)
      else
        throw new NonUniqueResultException()
    }
  }

  implicit def query2RichQuery[T](q: TypedQuery[T]) = new RichTypedQuery[T](q)
}

1

এই কোডটি দেখুন:

return query.getResultList().stream().findFirst().orElse(null);

যখন findFirst()বলা হয় তখন একটি নলপয়েন্টার এক্সসেপশন নিক্ষেপ করা যেতে পারে।

সেরা aproach হয়:

return query.getResultList().stream().filter(Objects::nonNull).findFirst().orElse(null);


0

সুতরাং এই পৃষ্ঠায় "ব্যতিক্রম ছাড়াই পুনর্লিখনের চেষ্টা করুন" সমাধানের সমস্তটিরই একটি গৌণ সমস্যা রয়েছে। হয় এটি নন-ইউনিক ব্যতিক্রম ছোঁড়াচ্ছে না বা এটিকে কিছু ভুল ক্ষেত্রেও ফেলেছে না (নীচে দেখুন)।

আমি মনে করি সঠিক সমাধানটি হ'ল (সম্ভবত):

public static <L> L getSingleResultOrNull(TypedQuery<L> query) {
    List<L> results = query.getResultList();
    L foundEntity = null;
    if(!results.isEmpty()) {
        foundEntity = results.get(0);
    }
    if(results.size() > 1) {
        for(L result : results) {
            if(result != foundEntity) {
                throw new NonUniqueResultException();
            }
        }
    }
    return foundEntity;
}

তালিকায় 0 টি উপাদান থাকলে নাল দিয়ে এটির ফিরে আসা, তালিকার বিভিন্ন উপাদান থাকলে নুনুফিক ফিরিয়ে দেওয়া, তবে আপনার নির্বাচনের কোনও একটি সঠিকভাবে নকশিত না হয়ে এবং একই জিনিসটিকে আরও একবারে ফেরত দেওয়ার পরে নুনুফিক প্রত্যাবর্তন করবে না।

মতামত নির্দ্বিধায়।


0

আমি ফলাফলের তালিকা পেয়ে এটি অর্জন করে তা খালি কিনা তা যাচাই করে

public boolean exist(String value) {
        List<Object> options = getEntityManager().createNamedQuery("AppUsers.findByEmail").setParameter('email', value).getResultList();
        return !options.isEmpty();
    }

এটি এত বিরক্তিকর যে getSingleResult()ব্যতিক্রম ছোঁড়ে

ছোঁড়ার:

  1. NoResultException - যদি কোনও ফলাফল না থাকে
  2. ননউইনিক রিসাল্ট এক্সসেপশন - যদি একের বেশি ফলাফল হয় এবং কিছু ব্যতিক্রম হয় যে আপনি তাদের ডকুমেন্টেশন থেকে আরও তথ্য পেতে পারেন

-3

আমার পক্ষে কাজ করে:

Optional<Object> opt = Optional.ofNullable(nativeQuery.getSingleResult());
return opt.isPresent() ? opt.get() : null;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.