হাইবারনেট এইচকিউএল ফলাফলের সাথে কীভাবে সুরক্ষা সতর্কতা এড়ানো যায়?


105

উদাহরণস্বরূপ আমার কাছে এমন প্রশ্ন রয়েছে:

Query q = sess.createQuery("from Cat cat");
List cats = q.list();

যদি আমি এটির মতো কিছু করার চেষ্টা করি তবে এটি নীচের সতর্কতাটি দেখায়

Type safety: The expression of type List needs unchecked conversion to conform to List<Cat>


List<Cat> cats = q.list();

এড়াতে কি উপায় আছে?


11
এটি উল্লেখ করার মতো বিষয় যে জেপিএর সাথে আপনার টাইপটি নিরাপদ প্রশ্নগুলি থাকতে পারে, টাইপটি ক্রিয়েওকুয়েরিতে যুক্ত করে।
এলাজার লাইবোভিচ

5
একটু দেরি হলেও sess.createQuery("from Cat cat", Cat.class);এলাজার যেমন উল্লেখ করেছেন।
ডোমিনিক মোহর

উত্তর:


99

@SuppressWarningsপ্রস্তাবিত হিসাবে, সর্বত্র ব্যবহার করা এটি করার একটি ভাল উপায়, যদিও প্রতিবার আপনি কল করার সময় এতে কিছুটা আঙুল টাইপ করা জড়িত না q.list()

আরও দুটি কৌশল রয়েছে যা আমি পরামর্শ দিই:

একজন কাস্ট-হেল্পার লিখুন

কেবল আপনার সমস্ত @SuppressWarningsজায়গায় এক জায়গায় রিফ্যাক্টর করুন :

List<Cat> cats = MyHibernateUtils.listAndCast(q);

...

public static <T> List<T> listAndCast(Query q) {
    @SuppressWarnings("unchecked")
    List list = q.list();
    return list;
}

অনিবার্য সমস্যাগুলির জন্য সতর্কতা উত্সাহিত করা থেকে গ্রহনকে রোধ করুন

ইক্লিপসে, উইন্ডো> পছন্দসমূহ> জাভা> সংকলক> ত্রুটি / সতর্কতাতে যান এবং জেনেরিক ধরণের অধীনে, চেকবক্সটি নির্বাচন করুন Ignore unavoidable generic type problems due to raw APIs

এটি উপরে বর্ণিত সমস্যার মতো অনাবশ্যক সতর্কতাগুলি বন্ধ করবে যা অনিবার্য।

কিছু মন্তব্য:

  • আমি Queryফলাফলের পরিবর্তে পাস করতে বেছে নিয়েছি q.list()কারণ এই "প্রতারণামূলক" পদ্ধতিটি কেবল হাইবারনেটের সাথে প্রতারণার জন্য ব্যবহার করা যেতে পারে, এবং Listসাধারণভাবে কোনও প্রতারণার জন্য নয় ।
  • আপনি .iterate()ইত্যাদি জন্য অনুরূপ পদ্ধতি যোগ করতে পারে ।

20
প্রথম নজরে, কালেকশন.চেকডলিস্ট (সংগ্রহ <E>, শ্রেণি <E>) পদ্ধতিটি নিখুঁত সমাধানের মতো দেখায়। তবে জাভাডক বলে যে এটি পদ্ধতিটি যে টাইপসেফ ভিউ তৈরি করে তা কেবল টাইপ করা উপাদানগুলিকে ভুলভাবে টাইপ করা থেকে বিরত করে। প্রদত্ত তালিকায় কোনও চেকিং করা হয় না।
ফটব্লাত

11
"তালিকা <<< তালিকা = সংগ্রহসমূহচেকডলিস্ট (কিউ.লিস্ট (), ক্যাট ক্লাস)" " এখনও গ্রহদেহে একটি "@প্রেস ওয়ার্নিংস" দরকার। অন্যান্য টিপ সম্পর্কে: "লিস্টএন্ডকাস্ট" টাইপ করা "@ সাপ্রেস ওয়ার্নিংস" এর চেয়ে খুব কম নয় যা একিপ্লের মাধ্যমে স্বয়ংক্রিয়ভাবে যুক্ত হয়।
ত্রিস্তান

2
Collections.checkedList()বিটিডাব্লু , পদ্ধতিটি চেক করা অ্যাসাইনমেন্ট সতর্কতাটিকে ছাঁটাই করবে না।
ডায়াবলো

39

প্রশ্নটি জিজ্ঞাসা করার পরে অনেক দিন হয়েছে তবে আমি আশা করি আমার উত্তর আমার মতো কারও পক্ষে সহায়ক হতে পারে।

আপনি javax.persistence কটাক্ষপাত করা তাহলে API ডক্স , আপনি যে কিছু নতুন পদ্ধতি যেহেতু যোগ করা হয়েছে দেখতে হবে Java Persistence 2.0। তাদের মধ্যে একটি createQuery(String, Class<T>)যা প্রত্যাবর্তন করে TypedQuery<T>। এই ছোট পার্থক্যের সাথে TypedQueryআপনি যেমনটি করেছিলেন ঠিক তেমনই আপনি ব্যবহার করতে পারেন Queryযে সমস্ত ক্রিয়াকলাপ এখন নিরাপদ।

সুতরাং, কেবল আপনার কোডটি এরকম স্মিথে পরিবর্তন করুন:

Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();

এবং আপনি সব প্রস্তুত।


1
প্রশ্নটি জেপিএ সম্পর্কিত নয়
ম্যাথিজস সেগার্স

2
হাইবারনেটের সাম্প্রতিক সংস্করণগুলি জেপিএ 2.x প্রয়োগ করে, তাই এই উত্তরটি প্রাসঙ্গিক।
ক্যাস্পিনো

টাইপকুইয়ারি <T> সেরা দৃশ্য।
মুনিব মীর্জা

21

আমরা @SuppressWarnings("unchecked")পাশাপাশি ব্যবহার করি তবে আমরা প্রায়শই এটি কেবল ভেরিয়েবলের ঘোষণায় ব্যবহার করার চেষ্টা করি না পুরো পদ্ধতিতে:

public List<Cat> findAll() {
    Query q = sess.createQuery("from Cat cat");
    @SuppressWarnings("unchecked")
    List<Cat> cats = q.list();
    return cats;
}

15

TypedQueryপরিবর্তে ব্যবহার করার চেষ্টা করুন Query। উদাহরণস্বরূপ এর পরিবর্তে: -

Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();

এটা ব্যবহার কর:-

TypedQuery<Cat> q1 = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q1.list();

1
Criteriaযদিও এটি করার কোনও উপায় আছে ?
স্টিলথ রাব্বি

5

আমাদের কোডে আমরা কলিং পদ্ধতিগুলি এর সাথে টিকিয়ে রাখি:

@SuppressWarnings ( "অবারিত")

আমি জানি এটি হ্যাকের মতো মনে হয় তবে একজন সহ-বিকাশকারী সম্প্রতি পরীক্ষা করে দেখেছিলেন যে আমরা যা করতে পেরেছি তা কেবল।


5

স্পষ্টতই, হাইবারনেট এপিআই-এ কোয়েরি.লিস্ট () পদ্ধতিটি "ডিজাইনের মাধ্যমে" নিরাপদ নয় এবং এটি পরিবর্তন করার কোনও পরিকল্পনা নেই

আমি বিশ্বাস করি যে সংকলক সতর্কতাগুলি এড়ানোর সহজ সমাধানটি হ'ল @ সাপ্রেস ওয়ার্নিংস ("চেক না করা") যুক্ত করা। এই টীকাটি পদ্ধতির স্তরে বা কোনও পদ্ধতির অভ্যন্তরে, পরিবর্তনশীল ঘোষণার ঠিক আগে স্থাপন করা যেতে পারে

আপনার কাছে এমন একটি পদ্ধতি রয়েছে যা ক্যোয়ারি.লিস্ট () সরবরাহ করে এবং তালিকা (বা সংগ্রহ) ফেরত দেয়, আপনি একটি সতর্কতাও পান। তবে এইটিকে @ সাপ্রেস ওয়ার্নিংস ("কাঁচা টাইপস") ব্যবহার করে চাপা দেওয়া হয়েছে।

ম্যাট কোয়েল প্রস্তাবিত তালিকাঅ্যান্ডকাস্ট (ক্যোয়ারী) পদ্ধতিটি কোয়েরি.লিস্ট () এর চেয়ে কম নমনীয়। যদিও আমি এটি করতে পারি:

Query q = sess.createQuery("from Cat cat");
ArrayList cats = q.list();

আমি যদি নীচের কোডটি চেষ্টা করি:

Query q = sess.createQuery("from Cat cat");
ArrayList<Cat> cats = MyHibernateUtils.listAndCast(q);

আমি একটি সংকলন ত্রুটি পেয়েছি: অমিল টাইপ করুন: তালিকা থেকে অ্যারেলিস্টে রূপান্তর করতে পারে না


1
"এটি পরিবর্তন করার কোনও পরিকল্পনা নেই।" - এটি ২০০৫ সালের একটি পোস্ট things
রুপ

4

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


2

না, তবে আপনি এটিকে নির্দিষ্ট ক্যোয়ারী পদ্ধতিতে আলাদা করতে পারেন এবং একটি @SuppressWarnings("unchecked")টীকা সহ সতর্কতাগুলি দমন করতে পারেন ।


ভুল ... জো ডিন ঠিক আছে, আপনি এটি ব্যবহার করতে পারেন? সতর্কতাগুলি এড়াতে জেনেরিক ধরণের হিসাবে ...
মাইক স্টোন

1
এটা সত্যি না. আপনি যদি একটি তালিকা <?> ব্যবহার করেন তবে আপনি অনুরূপ তালিকা তৈরি এবং প্রতিটি আইটেম কাস্ট করার অপ্রয়োজনীয় পদক্ষেপ ব্যতীত ক্যাট এর তালিকার উপাদানগুলি ব্যবহার করতে পারবেন না।
ডেভ এল।

ভাল, আপনি যদি কাস্টিংয়ের মাধ্যমে ফলাফলগুলি সরাসরি ব্যবহার করেন তবে আপনাকে তালিকা তৈরি করার দরকার নেই, এবং নির্বিশেষে, প্রশ্নটি ছিল "এটি এড়াতে কোনও উপায় আছে", উত্তরটি অবশ্যই অবশ্যই হ্যাঁ (এমনকি সুপারের সতর্কতা ছাড়াই)
মাইক স্টোন

2

হাইবারনেটের নতুন সংস্করণগুলি এখন একটি প্রকারের নিরাপদ Query<T>বস্তুকে সমর্থন করে যাতে @SuppressWarningsসংকলক সতর্কতাগুলি দূরে সরে যেতে আপনাকে আর কোনও হ্যাক ব্যবহার বা প্রয়োগ করতে হবে না। ইন সেশন এপিআই , Session.createQueryএখন একটি টাইপ নিরাপদ ফিরে আসবে Query<T>অবজেক্ট। আপনি এটি এইভাবে ব্যবহার করতে পারেন:

Query<Cat> query = session.createQuery("FROM Cat", Cat.class);
List<Cat> cats = query.list();

যখন ক্যোয়ারির ফলাফল কোনও বিড়ালকে ফেরত দেবে না তখন আপনি এটি ব্যবহার করতে পারেন:

public Integer count() {
    Query<Integer> query = sessionFactory.getCurrentSession().createQuery("SELECT COUNT(id) FROM Cat", Integer.class);
    return query.getSingleResult();
}

অথবা আংশিক নির্বাচন করার সময়:

public List<Object[]> String getName() {
    Query<Object[]> query = sessionFactory.getCurrentSession().createQuery("SELECT id, name FROM Cat", Object[].class);
    return query.list();
}

1

আমাদেরও একই সমস্যা ছিল। তবে এটি আমাদের পক্ষে খুব বড় বিষয় ছিল না কারণ হাইবারনেট কোয়েরি এবং সেশন নিয়ে আমাদের আরও বড় সমস্যা সমাধান করতে হয়েছিল।

বিশেষ করে:

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

আমাদের জন্য তাই, আমাদের আছে:

  1. এমন একটি ইন্টারফেস তৈরি করুন (এমপ্লাফিউকিউয়ারি) যা ক্যোয়ারিকে প্রসারিত করে
  2. একটি শ্রেণি তৈরি করুন (AmplafiQueryImpl) যা এমপ্ল্যাফিকিউরি প্রসারিত করে এবং একটি org.hibernate.Query মোড়ক করে
  3. একটি Txmanager তৈরি করুন যা কোনও Tx প্রদান করে।
  4. টিএক্সের বিভিন্ন ক্রিয়েকিউয়ারি পদ্ধতি রয়েছে এবং এমপ্লাফিকুইআরআইপিএল প্রদান করে

এবং সবশেষে,

আম্প্ল্যাফিউকিরিতে একটি "অ্যাসলিস্ট ()" থাকে যা কোয়েরি.লিস্টের জেনেরিক সক্ষম সংস্করণ () এমপ্ল্যাফিউকুইয়ের একটি "অনন্য ()" রয়েছে যা কোয়েরি.উনিকআরেসাল্ট () এর একটি জেনেরিক সক্ষম সংস্করণ (এবং কেবল একটি নিক্ষেপ না করে একটি সমস্যা লগ করে ব্যতিক্রম)

এটি কেবলমাত্র @ সাপ্রেস ওয়ার্নিংস এড়ানোর জন্য অনেক কাজ। তবে, আমি যেমন বলেছি (এবং তালিকাভুক্ত) রয়েছে আরও অনেক ভাল! মোড়কের কাজটি করার কারণ।


0

আমি জানি এটি পুরনো তবে 2 পয়েন্টগুলি ম্যাট কোয়েলেস উত্তরটিতে নোট করুন।

পয়েন্ট 1

এই

List<Cat> cats = Collections.checkedList(Cat.class, q.list());

এই হওয়া উচিত

List<Cat> cats = Collections.checkedList(q.list(), Cat.class);

পয়েন্ট 2

এটা থেকে

List list = q.list();

এই

List<T> list = q.list();

অন্যান্য জবাবদিহি হ্রাস করতে হবে স্পষ্টতই মূল জবাব ট্যাগ ব্রাউজার দ্বারা ছাঁটাই ছিল।


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


-1

হাইবারনেট ক্যোয়ারী সহ ধরণের সুরক্ষা সতর্কতা এড়ানোর একটি ভাল সমাধান হ'ল টর্পেডো কিউকুরির মতো একটি সরঞ্জাম ব্যবহার করে আপনাকে নিরাপদ এইচকিএল টাইপ তৈরি করতে সহায়তা করে।

Cat cat = from(Cat.class);
org.torpedoquery.jpa.Query<Entity> select = select(cat);
List<Cat> cats = select.list(entityManager);

-1
TypedQuery<EntityName> createQuery = entityManager.createQuery("from EntityName", EntityName.class);
List<EntityName> resultList = createQuery.getResultList();

3
আপনার সমাধানটি কীভাবে কাজ করে সে সম্পর্কে দয়া করে একটি সুন্দর বর্ণনা দেওয়ার চেষ্টা করুন। দেখুন: আমি কীভাবে ভাল উত্তর লিখব? । ধন্যবাদ।
শ্রী

1
আপনি কি কোডটিতে এমন কিছু ব্যাখ্যা যুক্ত করতে পারেন যা অন্যরা এটি থেকে শিখতে পারে?
নিকো হাজে

-6

আপনি যদি @ সাপ্রেস ওয়ার্নিংস ("চেক না করা") ব্যবহার করতে না চান তবে আপনি নিম্নলিখিতটি করতে পারেন।

   Query q = sess.createQuery("from Cat cat");
   List<?> results =(List<?>) q.list();
   List<Cat> cats = new ArrayList<Cat>();
   for(Object result:results) {
       Cat cat = (Cat) result;
       cats.add(cat);
    }

এফওয়াইআই - আমি এমন একটি ব্যবহারের পদ্ধতি তৈরি করেছি যা এটি আমার পক্ষে হয় যাতে এটি আমার কোডটি লিচু না করে এবং আমাকে @ সপ্রেস ওয়ার্নিং ব্যবহার করতে হবে না।


2
এটা ঠিক বোকা। সম্পূর্ণ সংকলক সম্পর্কিত সমস্যা কাটিয়ে ওঠার জন্য আপনি রানটাইম ওভারহেড যুক্ত করছেন। মনে রাখবেন যে প্রকার আর্গুমেন্টগুলি পুনরায় সংশোধিত হয় না তাই ধরণের কোনও রানটাইম চেকিং নেই।
জন নিলসন

সম্মতি জানানো হয়েছে, আপনি যদি এখনও এর মতো কিছু করতে চান তবে এর সাথে রানটাইম চেকিং যুক্ত করতে পারেন: তালিকা <<< বিড়াল = সংগ্রহসমূহ; চেকডলিস্ট (নতুন অ্যারেলিস্ট <চ্যাট> (), ক্যাট ক্লাস); cats.addAll (q.list ()); এই কাজ করা উচিত.
ddcruver
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.