জেপিএ উত্তরাধিকার @ এন্টিটি গ্রাফের মধ্যে সাবক্লাসের alচ্ছিক সমিতি অন্তর্ভুক্ত রয়েছে


12

নিম্নলিখিত ডোমেন মডেলটি দেওয়া, আমি Answerতাদের Valueও তাদের নিজ নিজ সাব-শিশু সহ সমস্তগুলি লোড করতে এবং এটিতে AnswerDTOJSON এ রূপান্তর করতে চাই। আমার একটি কার্যকরী সমাধান রয়েছে তবে এটি এন + 1 সমস্যায় ভুগছে যা আমি একটি অ্যাড-হক ব্যবহার করে পরিত্রাণ পেতে চাই @EntityGraph। সমস্ত সমিতি কনফিগার করা আছে LAZY

এখানে চিত্র বর্ণনা লিখুন

@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();

একটি বিজ্ঞাপন-হক ব্যবহার @EntityGraphউপর Repositoryআমি করতে পদ্ধতি নিশ্চিত করুন যে মূল্যবোধের ওপর n + 1 প্রতিরোধ প্রাক নিয়ে আসা হয় Answer->Valueসমিতি। যদিও আমার ফল জরিমানা সেখানে অলস লোড কারণ অন্য n + 1 সমস্যা হচ্ছে, selectedসমিতি MCValueগুলি।

এটি ব্যবহার করে

@EntityGraph(attributePaths = {"value.selected"})

ব্যর্থ হয়, কারণ selectedক্ষেত্রটি অবশ্যই কিছু Valueসংস্থার অংশ মাত্র :

Unable to locate Attribute  with the the given name [selected] on this ManagedType [x.model.Value];

selectedমানটি হ'ল আমি কীভাবে জেপিএকে সমিতিটি আনার চেষ্টা করতে পারি MCValue? আমি কিছু প্রয়োজন optionalAttributePaths

উত্তর:


8

EntityGraphঅ্যাসোসিয়েশন অ্যাট্রিবিউট সুপারক্লাসের অংশ এবং সমস্ত সাবক্লাসের অংশ হিসাবে আপনি কেবল তখনই এটি ব্যবহার করতে পারেন । অন্যথায়, আপনি বর্তমানে যা পাবেন EntityGraphতা সর্বদা ব্যর্থ Exceptionহবে।

আপনার এন +1 নির্বাচন ইস্যু এড়ানোর সর্বোত্তম উপায় হ'ল আপনার ক্যোয়ারিকে 2 ক্যোয়ারিতে বিভক্ত করা:

1 ম কোয়েরিটি অ্যাট্রিবিউট দ্বারা ম্যাপযুক্ত অ্যাসোসিয়েশন আনার জন্য MCValueএকটি ব্যবহার করে সত্তাগুলি আনে । এই ক্যোয়ারির পরে, এই সত্তাগুলি হাইবারনেটের প্রথম স্তরের ক্যাশে / অধ্যবসায় প্রসঙ্গে সংরক্ষণ করা হয়। হাইবারনেট এগুলিকে ব্যবহার করবে যখন এটি দ্বিতীয় কোয়ের ফলাফলের প্রক্রিয়া করবে।EntityGraphselected

@Query("SELECT m FROM MCValue m") // add WHERE clause as needed ...
@EntityGraph(attributePaths = {"selected"})
public List<MCValue> findAll();

২ য় ক্যোয়ারীটি Answerসত্তাটি আনবে এবং EntityGraphসম্পর্কিত Valueসংস্থাগুলি আনতে একটি ব্যবহার করে । প্রতিটি Valueসত্তার জন্য, হাইবারনেট নির্দিষ্ট সাবক্লাসটি তাত্ক্ষণিকভাবে পরীক্ষা করবে এবং চূড়ান্তভাবে প্রথম স্তরের ক্যাশে সেই শ্রেণি এবং প্রাথমিক কী সংমিশ্রনের জন্য কোনও বস্তু রয়েছে কিনা তা যাচাই করবে। যদি এটি হয় তবে হাইবারনেট কোয়েরিতে ফিরে আসা ডেটার পরিবর্তে প্রথম স্তরের ক্যাশে থেকে অবজেক্টটি ব্যবহার করে।

@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();

কারণ ইতিমধ্যে আমরা সব সংগৃহীত MCValueযুক্ত সঙ্গে সত্ত্বা selectedসত্ত্বা, আমরা এখন পেতে Answerএকটি সক্রিয়া সঙ্গে সত্ত্বা valueসমিতি। এবং যদি সমিতিতে কোনও MCValueসত্তা থাকে তবে এর selectedসমিতিটিও সূচনা করা হবে।


আমি দুটি জিজ্ঞাসা থাকার বিষয়ে ভেবেছিলাম, উত্তরগুলি আনার জন্য প্রথম 1 + মান এবং একটি selectedউত্তর আছে এমন উত্তরগুলির জন্য 2 তম উত্তর MCValue। আমি অপছন্দ করি যে এটির জন্য অতিরিক্ত লুপের প্রয়োজন হবে এবং ডেটা সেটগুলির মধ্যে ম্যাপিংটি পরিচালনা করতে হবে। এর জন্য হাইবারনেট ক্যাশেটি কাজে লাগানো আপনার ধারণাটি আমি পছন্দ করি। ফলাফলটি রক্ষার জন্য ক্যাশে নির্ভর করা কতটা নিরাপদ (ধারাবাহিকতার দিক দিয়ে) আপনি বিশদ বর্ণনা করতে পারেন? প্রশ্নগুলি লেনদেনের সময় করা হলে এটি কি কাজ করে? আমি স্পট এবং অল্প অলস প্রারম্ভিক ত্রুটিগুলি থেকে কঠিন hard
আটকে

1
আপনাকে একই লেনদেনের মধ্যে উভয় প্রশ্নের সম্পাদন করতে হবে। যতক্ষণ আপনি এটি করেন, এবং আপনার অধ্যবসায়ের প্রসঙ্গটি সাফ করবেন না, এটি একেবারেই নিরাপদ। আপনার প্রথম স্তরের ক্যাশে সর্বদা MCValueসত্তা থাকবে। এবং আপনার অতিরিক্ত লুপের দরকার নেই। আপনার MCValue1 টি ক্যোয়ারির সাথে সমস্ত সত্তা আনতে হবে যা এতে যোগ দেয় Answerএবং আপনার বর্তমান ক্যোয়ারির মতো একই WHERE ধারাটি ব্যবহার করে। আমি আজকের লাইভ স্ট্রিমে এটি সম্পর্কেও কথা বলেছি: youtu.be/70B9znTmi00?t=238 এটি 3:58 এ শুরু হয়েছিল তবে আমি এর মধ্যে আরও কয়েকটি প্রশ্ন নিয়েছি ...
থরবেন জনসান

দুর্দান্ত, ফলোআপের জন্য ধন্যবাদ! এছাড়াও আমি যোগ করতে চাই, যে এই সমাধানের জন্য সাবক্লাসে 1 টি ক্যোয়ারী দরকার। সুতরাং রক্ষণাবেক্ষণযোগ্যতা আমাদের জন্য ঠিক আছে তবে এই সমাধানটি সব ক্ষেত্রে উপযুক্ত নাও হতে পারে।
আটকে গেছে

আমার আমার শেষ মন্তব্যটি কিছুটা সংশোধন করা দরকার: অবশ্যই আপনার কেবল সাবক্লাসের জন্য একটি প্রশ্নের প্রয়োজন যা সমস্যায় ভুগছে। এছাড়াও এটি লক্ষণীয় যে সাবক্লাসের বৈশিষ্ট্যগুলির জন্য এটি ব্যবহার করার কারণে এটি কোনও বিষয়টিকে মৌমাছি করে না বলে মনে হয় SINGLE_TABLE_INHERITANCE
আটকে গেল

7

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

@EntityView(Answer.class)
interface AnswerDTO {
  @IdMapping
  Long getId();
  ValueDTO getValue();
}
@EntityView(Value.class)
@EntityViewInheritance
interface ValueDTO {
  @IdMapping
  Long getId();
}
@EntityView(TextValue.class)
interface TextValueDTO extends ValueDTO {
  String getText();
}
@EntityView(RatingValue.class)
interface RatingValueDTO extends ValueDTO {
  int getRating();
}
@EntityView(MCValue.class)
interface TextValueDTO extends ValueDTO {
  @Mapping("selected.id")
  Set<Long> getOption();
}

ব্লেজ-অধ্যবসায়ের দ্বারা সরবরাহিত বসন্তের ডেটা ইন্টিগ্রেশনের মাধ্যমে আপনি এর মতো একটি সংগ্রহস্থল সংজ্ঞায়িত করতে পারেন এবং ফলাফলটি সরাসরি ব্যবহার করতে পারেন

@Transactional(readOnly = true)
interface AnswerRepository extends Repository<Answer, Long> {
  List<AnswerDTO> findAll();
}

এটি একটি এইচকিউএল কোয়েরি উত্পন্ন করবে AnswerDTOযা নীচের মত কিছু যা আপনি ম্যাপ করেছেন ঠিক তা নির্বাচন করে।

SELECT
  a.id, 
  v.id,
  TYPE(v), 
  CASE WHEN TYPE(v) = TextValue THEN v.text END,
  CASE WHEN TYPE(v) = RatingValue THEN v.rating END,
  CASE WHEN TYPE(v) = MCValue THEN s.id END
FROM Answer a
LEFT JOIN a.value v
LEFT JOIN v.selected s

আমি আপনার লাইব্রেরিতে যে ইঙ্গিতটি পেয়েছি তার জন্য ইঙ্গিতটির জন্য হুম ধন্যবাদ, তবে আমরা এটি 2 টি মূল কারণে ব্যবহার করব না: 1) আমরা আমাদের প্রকল্পের সময়কালে সমর্থিত লাইবের উপর নির্ভর করতে পারি না (আপনার সংস্থার ব্লেজেবিট বরং ছোট এবং এর শুরুতে)। 2) আমরা একটি জটিল জিজ্ঞাসা অপ্টিমাইজ করার জন্য আরও জটিল প্রযুক্তি-স্ট্যাকের প্রতিশ্রুতিবদ্ধ করব না। (আমি জানি যে আপনার লিবিব আরও কিছু করতে পারে তবে আমরা একটি সাধারণ প্রযুক্তি স্ট্যাক পছন্দ করি এবং জেপিএ সমাধান না হলে কেবল একটি কাস্টম ক্যোয়ারী / ট্রান্সফরমেশন বাস্তবায়ন করব)।
আটকে

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

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

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

1
আপনার উত্তরে দেখার সংজ্ঞাটি হওয়া উচিতinterface MCValueDTO extends ValueDTO { @Mapping("selected.id") Set<Long> getOption(); }
আটকে

0

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

আমাদের ডেটা প্রবাহ দেখতে এমন কিছু দেখাচ্ছে:

  1. গ্রাফিক্যুয়াল অনুরোধ গ্রহণ করুন
  2. গ্রাফকিউএল অনুরোধটি পার্স করুন এবং কোয়েরিতে সত্তা গ্রাফ নোডের তালিকায় রূপান্তর করুন
  3. আবিষ্কৃত নোডগুলি থেকে সত্তা গ্রাফ তৈরি করুন এবং কার্যকর করার জন্য সংগ্রহস্থলে প্রবেশ করুন

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

এটি সন্ধানের আগে আমি স্প্রিং জেপিএ / হাইবারনেট ডক্সে প্রস্তাবিত প্রতিটি বিকল্প এবং অন্য বিকল্প ব্যবহার করে দেখেছি, তবে কিছুই সুন্দরভাবে বা কমপক্ষে এক টন অতিরিক্ত কোড দিয়ে সমস্যার সমাধান করতে পারে বলে মনে হয় নি nothing


এটি কীভাবে সুপার টাইপ থেকে জানা যায় না লোডিং সংঘের সমস্যা সমাধান করবে? এছাড়াও, যেমন অন্য উত্তরে বলা হয়েছে, আমরা জানতে চাই যে একটি খাঁটি জেপিএ সমাধান আছে কিনা, তবে আমি আরও মনে করি যে এই লিব একই ধরণের সমস্যায় ভোগে যেটি selectedসমিতি সব ধরণের জন্য উপলব্ধ নয় value
আটকে গেছে

: আপনি GraphQL আগ্রহী, আমরা এর graphql জাভা সঙ্গে আলোকচ্ছটা-অধ্যবসায় সত্তা দেখেছে একটি ইন্টিগ্রেশন আছে persistence.blazebit.com/documentation/1.5/entity-view/manual/...
খ্রিস্টান Beikov

@ ক্রিশ্চিয়ানিকোভো ধন্যবাদ জানায় তবে আমরা আমাদের মডেল / পদ্ধতিগুলি থেকে কর্মপরিকল্পনা তৈরির জন্য এসকিউপিআর ব্যবহার করছি
আর্বর

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

0

আপনার মন্তব্যের পরে সম্পাদিত:

আমার ক্ষমাপ্রার্থনা, আপনি প্রথম রাউন্ডে ইস্যু করেছিলাম না, আপনার সমস্যাটি স্প্রিং-ডেটা শুরু হওয়ার সময় ঘটে, আপনি যখন ফাইন্ডএল () এ কল করার চেষ্টা করেন কেবল তখনই হয় না।

সুতরাং, আপনি এখন পুরো উদাহরণটি নেভিগেট করতে পারেন আমার গিথুব থেকে টানা যেতে পারে: https://github.com/bdzzaid/stackoverflow-java/blob/master/jpa-hibernate/

আপনি সহজেই এই প্রকল্পটির অভ্যন্তরে আপনার সমস্যাটি পুনরুত্পাদন এবং ঠিক করতে পারেন।

কার্যকরভাবে, স্প্রিং ডেটা এবং হাইবারনেট ডিফল্টরূপে "নির্বাচিত" গ্রাফ নির্ধারণ করতে সক্ষম নয় এবং আপনাকে নির্বাচিত বিকল্প সংগ্রহ করার উপায় নির্দিষ্ট করতে হবে।

সুতরাং প্রথম, আপনি ক্লাসের NamedEntityGraphs ডিক্লেয়ার করা আছে উত্তর

যেহেতু আপনি দেখতে পারেন, দুই নয় NamedEntityGraph অ্যাট্রিবিউট জন্য মান ক্লাসের উত্তর

  • লোড করার জন্য নির্দিষ্ট সম্পর্ক ছাড়াই সমস্ত মানের জন্য প্রথম

  • নির্দিষ্ট মাল্টিচয়েস মানের জন্য দ্বিতীয় । আপনি যদি এটি অপসারণ করেন তবে আপনি ব্যতিক্রমটি পুনরুত্পাদন করুন।

দ্বিতীয়ত, আপনি একটি লেনদেনজনিত প্রেক্ষাপটে হতে হবে answerRepository.findAll () যদি আপনি ধরনের ডেটা আনতে চান অলস

@Entity
@Table(name = "answer")
@NamedEntityGraphs({
    @NamedEntityGraph(
            name = "graph.Answer", 
            attributeNodes = @NamedAttributeNode(value = "value")
    ),
    @NamedEntityGraph(
            name = "graph.AnswerMultichoice",
            attributeNodes = @NamedAttributeNode(value = "value"),
            subgraphs = {
                    @NamedSubgraph(
                            name = "graph.AnswerMultichoice.selected",
                            attributeNodes = {
                                    @NamedAttributeNode("selected")
                            }
                    )
            }
    )
}
)
public class Answer
{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false, nullable = false)
    private int id;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "value_id", referencedColumnName = "id")
    private Value value;
// ..
}

সমস্যা আনার সময় নয় valueএর -association Answerকিন্তু পেয়ে selectedক্ষেত্রে সমিতি valueএকটি হল MCValue। আপনার উত্তরে সে সম্পর্কিত কোনও তথ্য অন্তর্ভুক্ত নেই।
আটকে গেছে

@ থামুন আপনার উত্তরের জন্য ধন্যবাদ, আপনি দয়া করে আমার সাথে ক্লাস এমসিভ্যালু ভাগ করে নিতে পারেন, আমি স্থানীয়ভাবে আপনার ইস্যুটি পুনরুত্পাদন করার চেষ্টা করব।
বিডিজায়িদ

আপনাদের উদাহরণ কেবলমাত্র তখনই কাজ কারণ আপনার সমিতি সংজ্ঞায়িত OneToManyহিসাবে FetchType.EAGERকিন্তু প্রশ্ন বিবৃত: সমস্ত সমিতির হয় LAZY
আটকে গেছে

@ স্টক আমি আপনার শেষ আপডেটের পরে আমার উত্তর আপডেট করেছি, আশা করি আমার উত্তরটি আপনাকে আপনার সমস্যার সমাধান করতে সহায়তা করবে এবং entityচ্ছিক সম্পর্ক সহ এনটাইটেড গ্রাফ লোড করার উপায়টি বুঝতে সহায়তা করবে hope
বিডিজায়দ

আপনার "সমাধান" এখনও মূল এন + 1 সমস্যাটি ভোগ করে যা এই প্রশ্নটি নিয়ে রয়েছে: আপনার পরীক্ষার বিভিন্ন লেনদেনের জন্য সন্নিবেশ করান এবং আপনি দেখুন যে জেপিএ selectedপ্রতিটি উত্তরের জন্য সরাসরি ডিফল্ট লোড না করে একটি ডিবি কোয়েরি জারি করবে ।
আটকে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.