আপনি কীভাবে জেপিকিউএল বা এইচকিউএল-তে সীমাবদ্ধ ক্যোয়ারী করবেন?


239

হাইবারনেট 3 এ, এইচকিউএলে নিম্নলিখিত মাইএসকিউএল সীমার সমতুল্য করার উপায় আছে?

select * from a_table order by a_table_column desc limit 0, 20;

সম্ভব হলে আমি সেটম্যাক্সরোল্টস ব্যবহার করতে চাই না। হাইবারনেট / এইচকিউএল এর পুরানো সংস্করণে এটি অবশ্যই সম্ভব ছিল তবে এটি অদৃশ্য হয়ে গেছে বলে মনে হয়।


2
আমি ব্যবহার করছি Hibernate-5.0.12। এটি কি এখনও পাওয়া যায় না? এক মিলিয়ন বা তার বেশি রেকর্ড পাওয়া এবং তারপরে setMaxResultsএটির ফিল্টার প্রয়োগ করা সত্যিই ভারী হবে - এটি উপরের উপর @ র্যাচেলের দ্বারা @ স্কাফম্যানের উত্তরে লক্ষ্য করা গেছে।
রাজীব রঞ্জন

উত্তর:


313

এটি হাইবারনেট 2 তে নয় তবে হাইবারনেট 3 তে নয় কেন এটি জিজ্ঞাসা করা হয়েছিল যখন কয়েক বছর আগে এটি হাইবারনেট ফোরামে পোস্ট করা হয়েছিল :

সীমা এইচকিউএল-তে কোনও সমর্থিত ধারা ছিল না । আপনি setMaxResults () ব্যবহার করতে চাইছেন।

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

আমি মনে করি Query.setMaxResults()সত্যই আপনার একমাত্র বিকল্প।


3
আমি যুক্তি দিয়ে বলব যে হাইবারনেট 3 এর পদ্ধতিটি আরও সঠিক। হাইবারনেটের আপনার ব্যবহারটি ডেটাবেস-অজ্ঞাস্তিক হতে বোঝায় তাই আপনাকে বিমূর্ত পদ্ধতিতে এই ধরণের জিনিসগুলি করা উচিত।
ম্যাট বি

6
আমি সম্মত, তবে বৈশিষ্ট্যগুলি যেমন বাদ দেওয়া হয় তখন মাইগ্রেশনটি পাছায় রাজকীয় ব্যথা হয়।
স্কাফম্যান

52
তবে setMaxResults এর সাথে প্রথমে ক্যোয়ারী চালানো হয় এবং তারপরে আপনি যে ফলাফলটি কল করেন setMaxResultsযা ফলাফল সীমা থেকে সীমিত সংখ্যক ফলাফল সারি নেবে এবং এটি ব্যবহারকারীর কাছে প্রদর্শিত হবে, আমার ক্ষেত্রে আমার কাছে 3 মিলিয়ন রেকর্ড রয়েছে যা অনুসন্ধান করা হয়েছে এবং তারপরে সেটম্যাক্সারসাল্টসকে কল করতে কল করছি ৫০ টি রেকর্ড কিন্তু আমি তা করতে চাই না, নিজেই জিজ্ঞাসা করার সময় আমি 50 টি রেকর্ডের জন্য জিজ্ঞাসা করতে চাই, এমন কি উপায় আছে?
রাচেল

2
পুরাতন পোস্ট আমি জানি। আমি রাহেলের সাথে পুরোপুরি একমত এনএইচবারনেট (হাইবারনেটের নেট বন্দর) ব্যবহার করে, আমি সম্প্রতি 2 থেকে 3 এবং একই জিনিস থেকে আপগ্রেড করেছি, শীর্ষ এক্স এখন পার্সার ত্রুটি ফেলছে। যাইহোক, যখন আমি ক্যোয়ারীতে সেটম্যাক্সের ফলাফলগুলি যুক্ত করেছি, তখন এটি ফলাফল প্রাপ্ত এসকিউএলে (এমএসকিউএল ২০০8 ডায়ালেক্ট ব্যবহার করে) একটি শীর্ষ এক্স উত্পন্ন করেছিল। এটা ভাল.
থিয়েরি_

17
হাইচুয়েট সহ উইকিপিডিয়া র‌্যাচেল এই অংশটিকে কোয়েরিতে setMaxResultsযুক্ত করবে limit। এটি সব ফলাফল পাবেন না। এটি সক্ষম করে আপনি যে ক্যোয়ারী তৈরি করেছেন তা পরীক্ষা করতে পারেন:<property name="show_sql">true</property>
আন্দ্রেজ

148
 // SQL: SELECT * FROM table LIMIT start, maxRows;

Query q = session.createQuery("FROM table");
q.setFirstResult(start);
q.setMaxResults(maxRows);

6
আমি এটিকে সবচেয়ে পছন্দ করি কারণ setFirstResultএই উত্তরটিতে প্রকৃতপক্ষে উল্লেখ করা হয়েছে যেখানে এখানে এবং অন্যত্র তারা অফসেটটি কীভাবে সেট করবেন তা উল্লেখ না করেই কেবল এটি বলে setMaxResultsএবং setMaxResultsএটি।
ডেমোঙ্গোলেম

19

আপনি ব্যবহার করতে না চান, তাহলে setMaxResults()উপর Queryবস্তু তারপর আপনি স্বাভাবিক এসকিউএল ব্যবহার করে সবসময় প্রত্যাবর্তন ফিরে পারে না।


37
আসলেই এতটা উত্তেজনাপূর্ণ কিছু নয়।
স্টিভডব্রাউন

8
আমি এইচকিউএলকেও উত্তেজনাপূর্ণ মনে করি না। আপনার ডিবি সার্ভারে এমন কোনও দৃশ্য লিখুন না যা সীমাটি প্রযোজ্য এবং তারপরে এই ভিউ দেখার জন্য এইচকিউএল পাবেন: পি
পিজেপি

1
এটি কেবলমাত্র এই জিনিসগুলির মধ্যে একটি, যখন এসকিউএল প্রতিটি প্রশ্নের জন্য এইচকিউএল এর চেয়ে অনেক সহজ, ভিউ তৈরি করে এবং স্থানীয় এসকিউএল লেখার ক্ষেত্রে পুনঃসংশোধন করার জন্য এত দুর্দান্ত না হয়। আমি যখন পারি তখন এড়াতে চেষ্টা করি। প্রকৃত আসল সমস্যাটি হ'ল আমি যাই হোক না কেন আমার মাইএসকিউএল কোয়েরিটি ভুল লিখেছি এবং সেটআপ ম্যাক্সআরসাল্টগুলি অদ্ভুত বলে মনে করছিলাম। এটা ছিল না।
স্টিভডব্রাউন

এবং যদি আপনি বিভিন্ন ডিবিএমএস বিক্রেতাদের মধ্যে স্যুইচ করার চেষ্টা করেন তবে ব্যথা আপনার জন্য অপেক্ষা করছে।
ওলগুন কেয়া

5

আপনি যদি সেটম্যাক্সের ফলাফলগুলি ব্যবহার করতে না চান তবে আপনি তালিকার পরিবর্তে Query.scrol ব্যবহার করতে পারেন এবং আপনার সারিগুলি সন্ধান করতে পারেন। উদাহরণস্বরূপ পেজিংয়ের জন্য দরকারী।


ধন্যবাদ, গৃহীত উত্তরটি আমার পক্ষে সমস্যাটি সমাধান করে নি, কারণ setMaxResults()মেমরিতে প্রতিটি রেকর্ড প্রথমে লোড করে এবং পরে একটি উপ-তালিকা তৈরি করে, যা যখন কয়েক হাজার বা তার বেশি রেকর্ড থাকে সার্ভারকে ক্র্যাশ করে, কারণ এটি মেমরির বাইরে থাকে। আমি তবে জেপিএ টাইপ করা ক্যোয়ারী থেকে হাইবারনেট ক্যোয়ারিতে QueryImpl hibernateQuery = query.unwrap(QueryImpl.class)যেতে পারি এবং তারপরে আমি scroll()আপনার পরামর্শ মতো পদ্ধতিটি ব্যবহার করতে পারি could
টোঙ্গোর্জেজ

কমপক্ষে ওরাকল উপভাষার সাথে এটি সত্য নয় (হাইবারনেট ROWNUM ভার্চুয়াল কলামটি ব্যবহার করে)। এটি ড্রাইভারের উপর নির্ভর করে। অন্যান্য ডিবিদের শীর্ষ কার্য রয়েছে।
লুয়ুইস মার্টিনেজ

আমার ক্যোয়ারী একটি যোগদানের আনয়ন ব্যবহার করছে। এর ফলে হাইবারনেট সতর্কতা "সংগ্রহের আনার সাথে নির্দিষ্ট করা প্রথম ফলাফল / সর্বাধিক ফলাফল; স্মৃতিতে প্রয়োগ করা হয়" এর ফলাফল। একটি যোগদানের আনার সাথে, হাইবারনেট স্মৃতিতে পূর্ণ সংগ্রহ লোড করছে। পারফরম্যান্সের কারণে যুক্তটিকে বাদ দেওয়া কোনও বিকল্প নয়। আমি যখন স্ক্রোলযোগ্য ফলাফলগুলি ব্যবহার করি তখন কোন রেকর্ডটি মেমরিতে লোড হয় সে সম্পর্কে আমার আরও নিয়ন্ত্রণ থাকে। আমি একক স্ক্রোলযোগ্য ফলাফলের সাথে সমস্ত রেকর্ড লোড করতে পারি না, কারণ এর ফলে মেমরির বাইরেও আসে। আমি বিভিন্ন স্ক্রোলযোগ্য ফলাফলের সাথে একাধিক পৃষ্ঠাগুলি লোড করার পরীক্ষা করছি। এটি যদি কাজ না করে তবে আমি এসকিউএল নিয়ে যাব।
টোঙ্গোর্জেজ

এটা অদ্ভুত, আমি এর আগে কখনও মুখোমুখি হই নি। হ্যাঁ কখনও কখনও সোজা জেডিবিসি ব্যবহার করা বিশেষত বৃহত্তর / ব্যাচ প্রক্রিয়াগুলির জন্য।
লুয়ুইস মার্টিনেজ

@ অ্যান্টিওমন সম্পর্কগুলি আমার সমস্যাগুলির কারণ করছে। যদি কোনওভাবে আমি একাধিক মানকে একক মানকে সংলগ্ন করতে হাইবারনেটে ওরাকল সমষ্টি ফাংশন LISTAGG সম্পাদন করতে পারি, তবে আমি যোগদানগুলিকে বাদ দিতে পারি এবং এগুলি একটি উপবৃত্তির দ্বারা প্রতিস্থাপন করতে পারি।
টুঞ্জর্জেস

2

আপনি এটির জন্য সহজেই পৃষ্ঠাগুলি ব্যবহার করতে পারেন।

    @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value = "true") })
    @Query("select * from a_table order by a_table_column desc")
    List<String> getStringValue(Pageable pageable);

আপনাকে new PageRequest(0, 1)রেকর্ড আনতে এবং তালিকা থেকে প্রথম রেকর্ডটি আনতে হবে।


2

যেহেতু এটি একটি খুব সাধারণ প্রশ্ন, আমি এই নিবন্ধটি লিখেছি , যার ভিত্তিতে এই উত্তরটি ভিত্তিক।

setFirstResultএবং setMaxResults Queryপদ্ধতি

একটি জেপিএ এবং হাইবারনেটের জন্য Query, setFirstResultপদ্ধতিটি সমান OFFSET, এবং setMaxResultsপদ্ধতিটি লিমিটের সমতুল্য:

List<Post> posts = entityManager
.createQuery(
    "select p " +
    "from Post p " +
    "order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();

LimitHandlerবিমূর্তন

হাইবারনেট LimitHandlerডাটাবেস-নির্দিষ্ট পৃষ্ঠাগুলি যুক্তি সংজ্ঞায়িত করে এবং নিম্নলিখিত চিত্র দ্বারা চিত্রিত হিসাবে, হাইবারনেট অনেকগুলি ডাটাবেস-নির্দিষ্ট পৃষ্ঠাগুলি বিকল্প সমর্থন করে:

<কোড> লিমিটহ্যান্ডলার </ কোড> বাস্তবায়ন

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

মাইএসকিউএল

SELECT p.id AS id1_0_,
       p.created_on AS created_2_0_,
       p.title AS title3_0_
FROM post p
ORDER BY p.created_on
LIMIT ?, ?

পোস্টগ্রি

SELECT p.id AS id1_0_,
       p.created_on AS created_2_0_,
       p.title AS title3_0_
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?

SQL সার্ভার

SELECT p.id AS id1_0_,
       p.created_on AS created_on2_0_,
       p.title AS title3_0_
FROM post p
ORDER BY p.created_on
OFFSET ? ROWS 
FETCH NEXT ? ROWS ONLY

আকাশবাণী

SELECT *
FROM (
    SELECT 
        row_.*, rownum rownum_
    FROM (
        SELECT 
            p.id AS id1_0_,
            p.created_on AS created_on2_0_,
            p.title AS title3_0_
        FROM post p
        ORDER BY p.created_on
    ) row_
    WHERE rownum <= ?
)
WHERE rownum_ > ?

ব্যবহারের সুবিধা setFirstResultএবংsetMaxResults হাইডারনেট কোনও সমর্থিত রিলেশনাল ডাটাবেসগুলির জন্য ডাটাবেস-নির্দিষ্ট পৃষ্ঠাগুলি সিনট্যাক্স তৈরি করতে পারে।

এবং, আপনি কেবল জেপিকিউএল কোয়েরিতে সীমাবদ্ধ নন। আপনি ব্যবহার করতে পারেনsetFirstResultsetMaxResultsনেটিভ এসকিউএল প্রশ্নের জন্য এবং পদ্ধতিটি সাতটি ।

নেটিভ এসকিউএল কোয়েরি

নেটিভ এসকিউএল কোয়েরিগুলি ব্যবহার করার সময় আপনাকে ডাটাবেস-নির্দিষ্ট পৃষ্ঠাগুলি হার্ডকোড করতে হবে না। হাইবারনেট এটি আপনার প্রশ্নের সাথে যুক্ত করতে পারে।

সুতরাং, আপনি যদি পোস্টগ্রিজ এসকিউএলে এই এসকিউএল কোয়েরিটি সম্পাদন করছেন:

List<Tuple> posts = entityManager
.createNativeQuery(
    "SELECT " +
    "   p.id AS id, " +
    "   p.title AS title " +
    "from post p " +
    "ORDER BY p.created_on", Tuple.class)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();

হাইবারনেট নিম্নলিখিত হিসাবে এটি রূপান্তরিত হবে:

SELECT p.id AS id,
       p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?

ঠিক আছে তো?

এসকিউএল-ভিত্তিক পৃষ্ঠাগুলি ছাড়িয়ে

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

পরীক্ষা করে দেখুন এই নিবন্ধটি আরো বিস্তারিত জানার জন্য।


1

String hql = "select userName from AccountInfo order by points desc 5";

এটি ব্যবহার না করে আমার পক্ষে কাজ করেছিল setmaxResults();

কীওয়ার্ডটি ব্যবহার না করে কেবল সর্বশেষে (এই ক্ষেত্রে 5) সর্বাধিক মান সরবরাহ করুন limit। : P: P


7
এইচএম ... এটি সম্পর্কে খুব বেশি নিশ্চিত নয়, [উদ্ধৃতি প্রয়োজন] এটি একটি দুর্ঘটনা হতে পারে এবং হঠাৎ হাইবারনেটের নতুন সংস্করণে কাজ করা বন্ধ করে দিতে পারে।
কনরাড 'ktoso' মালাউস্কি

4
অফিসিয়াল ডকুমেন্ট দেখুন।
Nhu Vy

1
এটি আমার জন্য হাইবারনেট সংস্করণ 5.2.12 ফাইনালে কাজ করছে না
jDub9

1
এটি কাজ করছে না, হাইবারনেট ৪.x সমর্থন করে না।
ফয়েজ আকরাম

0

আমার পর্যবেক্ষণটি হ'ল এমনকি এইচকিউএল (হাইবারনেট 3.x) এরও আপনার সীমা রয়েছে, এটি পার্সিং ত্রুটির কারণ হবে বা কেবল উপেক্ষা করা হবে। (যদি আপনার সীমাবদ্ধতার আগে + ডেস্ক / এএসসি দ্বারা অর্ডার থাকে তবে তা উপেক্ষা করা হবে, যদি আপনার সীমাবদ্ধতার আগে ডেস্ক / এসসি না থাকে তবে এটি পার্সিং ত্রুটির কারণ হবে)


0

যদি এই মোডে একটি সীমা পরিচালনা করতে পারেন

public List<ExampleModel> listExampleModel() {
    return listExampleModel(null, null);
}

public List<ExampleModel> listExampleModel(Integer first, Integer count) {
    Query tmp = getSession().createQuery("from ExampleModel");

    if (first != null)
        tmp.setFirstResult(first);
    if (count != null)
        tmp.setMaxResults(count);

    return (List<ExampleModel>)tmp.list();
}

এটি একটি সীমা বা একটি তালিকা পরিচালনা করার জন্য একটি খুব সহজ কোড।


0
Criteria criteria=curdSession.createCriteria(DTOCLASS.class).addOrder(Order.desc("feild_name"));
                criteria.setMaxResults(3);
                List<DTOCLASS> users = (List<DTOCLASS>) criteria.list();
for (DTOCLASS user : users) {
                System.out.println(user.getStart());
            }

0

আপনার একটি নেটিভ ক্যোয়ারী লিখতে হবে, এটি উল্লেখ করুন

@Query(value =
    "SELECT * FROM user_metric UM WHERE UM.user_id = :userId AND UM.metric_id = :metricId LIMIT :limit", nativeQuery = true)
List<UserMetricValue> findTopNByUserIdAndMetricId(
    @Param("userId") String userId, @Param("metricId") Long metricId,
    @Param("limit") int limit);


0

নীচে স্নিপেট এইচকিউএল ব্যবহার করে সীমাবদ্ধ ক্যোয়ারি সম্পাদন করতে ব্যবহৃত হয়।

Query query = session.createQuery("....");
query.setFirstResult(startPosition);
query.setMaxResults(maxRows);

আপনি এই লিঙ্কে ডেমো আবেদন পেতে পারেন ।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.