জেপিএ উত্সাহী আনতে যোগ দেয় না


112

জেপিএ আনার কৌশলটি ঠিক কী নিয়ন্ত্রণ করে? আমি আগ্রহী এবং অলস মধ্যে কোনও পার্থক্য সনাক্ত করতে পারি না। উভয় ক্ষেত্রেই জেপিএ / হাইবারনেট স্বয়ংক্রিয়ভাবে বহু-এক-এক সম্পর্কের সাথে যোগ দেয় না।

উদাহরণ: ব্যক্তির একক ঠিকানা রয়েছে। একটি ঠিকানা অনেক লোকের হতে পারে। জেপিএ টীকাযুক্ত সত্তা শ্রেণিগুলির মতো দেখতে:

@Entity
public class Person {
    @Id
    public Integer id;

    public String name;

    @ManyToOne(fetch=FetchType.LAZY or EAGER)
    public Address address;
}

@Entity
public class Address {
    @Id
    public Integer id;

    public String name;
}

আমি যদি জেপিএ কোয়েরি ব্যবহার করি:

select p from Person p where ...

জেপিএ / হাইবারনেট ব্যক্তি টেবিল থেকে নির্বাচন করতে একটি এসকিউএল কোয়েরি তৈরি করে এবং তারপরে প্রতিটি ব্যক্তির জন্য একটি পৃথক ঠিকানা জিজ্ঞাসা :

select ... from Person where ...
select ... from Address where id=1
select ... from Address where id=2
select ... from Address where id=3

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

আমি যখন স্পষ্টভাবে এটিতে যোগদানের জন্য বলি তখনই এটি আসলে যোগদান করবে:

select p, a from Person p left join p.address a where ...

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

সম্পাদনা: এটি প্রদর্শিত হয় (হাইবারনেট এফএকিউ এখানে এবং এখানে দেখুন ) যা FetchTypeজেপিএ প্রশ্নের উপর প্রভাব ফেলে না। সুতরাং আমার ক্ষেত্রে আমি স্পষ্টভাবে এটিতে যোগদানের জন্য বলেছি।


5
প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী এন্ট্রি লিংক ভাঙা হয়, এখানে কাজ করছে এক
n0weak

উত্তর:


99

জেপিএ আনার কৌশল নির্বাচন করার জন্য মানচিত্রের মানচিত্রের বিষয়ে কোনও স্পেসিফিকেশন সরবরাহ করে না। সাধারণভাবে, সম্পর্কিত সংস্থাগুলি নীচে দেওয়া যেকোন একটি উপায়ে সংগ্রহ করা যেতে পারে

  • নির্বাচন => মূল সত্তার জন্য একটি ক্যোয়ারী + সম্পর্কিত ম্যাপযুক্ত সত্তা / প্রতিটি মূল সত্তার সংগ্রহের জন্য একটি কোয়েরি = (এন + 1) ক্যোয়ারী
  • SUBSELECT => মূল সত্তার জন্য একটি ক্যোয়ারী + সম্পর্কিত ম্যাপযুক্ত সত্তার জন্য দ্বিতীয় কোয়েরি / প্রথম কোয়েরিতে প্রাপ্ত সমস্ত মূল সত্তার সংগ্রহ = 2 ক্যোয়ারী
  • উভয় মূল সত্তা এবং তাদের ম্যাপযুক্ত সত্তা / সংগ্রহ = 1 কোয়েরি উভয়কেই আনতে JOIN => একটি কোয়েরি

সুতরাং SELECTএবং JOINদুটি চূড়ান্ত হয় এবং SUBSELECTএর মধ্যে পড়ে। যে কেউ তার / তার ডোমেন মডেলের ভিত্তিতে উপযুক্ত কৌশল বেছে নিতে পারেন।

ডিফল্টরূপে SELECTJPA / EclipseLink এবং হাইবারনেট উভয় দ্বারা ব্যবহৃত হয়। এটি ব্যবহার করে ওভাররাইড করা যেতে পারে:

@Fetch(FetchMode.JOIN) 
@Fetch(FetchMode.SUBSELECT)

হাইবারনেটে এটি SELECTস্পষ্টভাবে ব্যবহার করে মোড সেট করার অনুমতি দেয় @Fetch(FetchMode.SELECT)যা ব্যাচের আকার যেমন ব্যবহার করে সুর করা যায় @BatchSize(size=10)

এক্সিলিপ লিঙ্কে সম্পর্কিত টীকাগুলি হ'ল:

@JoinFetch
@BatchFetch

5
কেন সেই সেটিংস বিদ্যমান? আমি মনে করি জিন প্রায় অবশ্যই ব্যবহার করা উচিত used এখন আমাকে হাইবারনেট-নির্দিষ্ট টীকা সহ সমস্ত ম্যাপিংস চিহ্নিত করতে হবে।
vbezhenar

4
আকর্ষণীয় তবে দুঃখজনকভাবে @ ফ্যাচ (ফেচমোড.জোঁইন) আমার (হাইবারনেট ৪.২.১৫), জেপিকিউএল এ মানদণ্ডের মতো কাজ করে না।
অ্যাপাক্স

3
হাইবারনেট টীকাটি আমার পক্ষে মোটেও কাজ করে না বলে মনে হচ্ছে, স্প্রিং জেপিএ
TheBakker

2
@ এএফএক্স এটি হতে পারে কারণ হাইবারনেট জেপিএকিউএল / মাপদণ্ড বনাম em.find () এর জন্য বিভিন্ন ডিফল্ট কৌশল ব্যবহার করে। দেখুন vladmihalcea.com/2013/10/17/... এবং রেফারেন্স ডকুমেন্টেশন।
জোশুয়া ডেভিস

1
@vbezhenar (এবং কিছুক্ষণ পরে তাঁর মন্তব্য পড়ে ওথস): জয়ন কোয়েরি ডাটাবেসে কার্টেসিয়ান পণ্য উত্পন্ন করে যাতে আপনার নিশ্চিত হওয়া উচিত যে আপনি কার্টেসিয়ান পণ্যটি গণনা করতে চান। মনে রাখবেন যে আপনি যদি ফেচ জয়েন ব্যবহার করেন তবে আপনি অলস রাখলে তা আগ্রহী হয়ে উঠবে।
ওয়ালফ্র্যাট

45

"এমএক্সসি" ঠিক আছে। সম্পর্কটি কখন সমাধান করা উচিত তা fetchTypeকেবল নির্দিষ্ট করে।

একটি বাইরের যোগদান ব্যবহার করে আগ্রহী লোডিং অনুকূল করতে আপনাকে যুক্ত করতে হবে

@Fetch(FetchMode.JOIN)

আপনার মাঠে এটি একটি হাইবারনেট নির্দিষ্ট টিকা।


6
এটি হাইপারনেট ৪.২.১৫ এর সাথে জেপিকিউএল বা মাপদণ্ডে কাজ করে না।
অ্যাফাক্স

6
@ এফ্যাক্স আমি মনে করি এটি কারণ জেপিএকিউএল এবং মানদণ্ডগুলি আনুন নির্দিষ্টকরণের মান্য করে না। আনার টীকাটি কেবলমাত্র এম.ফাইন্ড (), আফাইকের জন্য কাজ করে। Vladmihalcea.com/2013/10/17/… দেখুন, হাইবারনেট ডকসও দেখুন । আমি নিশ্চিত যে এটি কোথাও আচ্ছাদিত।
জোশুয়া ডেভিস

@ জোশুয়াডাভিস আমার অর্থ হ'ল F @ ফেনা টীকাগুলি কোয়েটারে, জেপিকিউএল বা এম.ফাইন্ড () এর মধ্যে কোনও ধরণের জয়েন্ট অপটিমাইজেশন প্রয়োগ করে না, হাইবারনেট ৫.২ নিয়ে আমার আরও একবার চেষ্টা করা হয়েছিল + এবং এটি এখনও একই
অ্যাফাক্স

38

প্রাথমিক সত্তা আনার সময় অবিলম্বে টীকাযুক্ত ক্ষেত্রটি আনা হয় কিনা তা ফেচটাইপ বৈশিষ্ট্যটি নিয়ন্ত্রণ করে। আনতে হবে কীভাবে ফেচ স্টেটমেন্টটি তৈরি করা হয়, আসল বর্গাকার বাস্তবায়ন আপনি যে সরবরাহকারীর উপরে টপলিংক / হাইবারনেট ব্যবহার করছেন তার উপর নির্ভর করে depends

যদি আপনি সেট করে থাকেন fetchType=EAGERতার অর্থ হ'ল টীকাগুলির ক্ষেত্রটি সত্তার অন্যান্য ক্ষেত্রগুলির সাথে একই সাথে এর মানগুলি সহ পপুলেট হয়। সুতরাং আপনি যদি কোনও সত্তা পরিচালক খোলেন তবে আপনার ব্যক্তির অবজেক্টগুলি পুনরুদ্ধার করে এবং সত্তাটি বন্ধ করে রাখেন, পরে একজন ব্যক্তি.এড্রেস করার ফলে অলস লোড ব্যতিক্রম ছোঁড়া হবে না।

আপনি যদি fetchType=LAZYক্ষেত্রটি সেট করেন তবে এটি অ্যাক্সেস পাওয়া মাত্র পপুলেট হবে। আপনি যদি সত্তাটি বন্ধ করে দিয়ে থাকেন তবে যদি কোনও ব্যক্তি.এড্রেস করেন তবে একটি অলস লোড ব্যতিক্রম ছোঁড়া হবে। ক্ষেত্রটি লোড করতে আপনার সত্ত্বাটি em.olve () এর সাহায্যে সত্তা প্রশাসনিক প্রসঙ্গে রাখতে হবে, তারপরে ক্ষেত্রটি অ্যাক্সেস করতে হবে এবং তারপরে সত্তা পরিচালককে বন্ধ করতে হবে।

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

প্রশ্নের দ্বিতীয় অংশের জন্য - কীভাবে অনুকূলিত এসকিউএল উত্পন্ন করতে হাইবারনেট পাবেন?

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


20

সাথে চেষ্টা করুন:

select p from Person p left join FETCH p.address a where...

এটি JPA2 / EclipseLink এর সাথে আমার অনুরূপভাবে কাজ করে, তবে মনে হয় এই বৈশিষ্ট্যটি JPA1 তেও উপস্থিত রয়েছে :


7

আপনি যদি হাইবারনেটের পরিবর্তে EclipseLink ব্যবহার করেন তবে আপনি "ক্যোয়ার ইঙ্গিতগুলি" দ্বারা আপনার অনুসন্ধানগুলি অনুকূল করতে পারেন। এক্সিলিপ উইকির এই নিবন্ধটি দেখুন: এক্লিপস লিঙ্ক / উদাহরণ / জেপিএ / কোয়েরিঅપ્টিমাইজেশন

"যোগ করা পড়া" সম্পর্কে একটি অধ্যায় রয়েছে।


2

যোগদানের জন্য আপনি একাধিক জিনিস করতে পারেন (এক্সপ্লিসিংক ব্যবহার করে)

  • jpql এ আপনি আনতে বাম অংশে করতে পারেন

  • নামযুক্ত ক্যোয়ারিতে আপনি ক্যোয়ারী ইঙ্গিতটি নির্দিষ্ট করতে পারেন

  • টাইপড কিওয়ারিতে আপনি এর মতো কিছু বলতে পারেন

    query.setHint("eclipselink.join-fetch", "e.projects.milestones");

  • ব্যাচ আনার ইঙ্গিতও আছে

    query.setHint("eclipselink.batch", "e.address");

দেখা

http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html


1

ব্যাক্তি শ্রেণীর একটি এম্বেডড কী ক্লাস ছিল এমন ব্যতিক্রম নিয়ে আমার ঠিক এই সমস্যাটি ছিল। আমার নিজের সমাধানটি ছিলো क्वेরিতে তাদের সাথে যোগ দেওয়া এবং সরানো

@Fetch(FetchMode.JOIN)

আমার এম্বেড করা আইডি ক্লাস:

@Embeddable
public class MessageRecipientId implements Serializable {

    @ManyToOne(targetEntity = Message.class, fetch = FetchType.LAZY)
    @JoinColumn(name="messageId")
    private Message message;
    private String governmentId;

    public MessageRecipientId() {
    }

    public Message getMessage() {
        return message;
    }

    public void setMessage(Message message) {
        this.message = message;
    }

    public String getGovernmentId() {
        return governmentId;
    }

    public void setGovernmentId(String governmentId) {
        this.governmentId = governmentId;
    }

    public MessageRecipientId(Message message, GovernmentId governmentId) {
        this.message = message;
        this.governmentId = governmentId.getValue();
    }

}

-1

আমার কাছে দুটি জিনিস ঘটে।

প্রথমত, আপনি কি নিশ্চিত যে আপনি ঠিকানার জন্য মুনটোটোইন? তার মানে একাধিক ব্যক্তির একই ঠিকানা থাকবে। যদি এটিগুলির মধ্যে একটির জন্য এটি সম্পাদিত হয় তবে এটি সবার জন্য সম্পাদনা করা হবে। এটা কি আপনার অভিপ্রায়? 99% সময় ঠিকানাগুলি "ব্যক্তিগত" (এই অর্থে যে তারা কেবলমাত্র একজন ব্যক্তির অন্তর্ভুক্ত)।

দ্বিতীয়ত, ব্যক্তি সত্তায় আপনার কি অন্য কোন আগ্রহী সম্পর্ক রয়েছে? যদি আমি সঠিকভাবে স্মরণ করি তবে হাইবারনেট কেবল কোনও সত্তার মধ্যে একটি আগ্রহী সম্পর্ক পরিচালনা করতে পারে তবে এটি সম্ভবত পুরানো তথ্য।

আমি বলছি যেহেতু আমি যেখানে বসে আছি সেখান থেকে আপনার কীভাবে এটি কাজ করা উচিত তা মূলত সঠিক।


এটি একটি তৈরি উদাহরণ যা বহু ব্যবহার করে। ব্যক্তি-ঠিকানা সর্বোত্তম উদাহরণ নাও হতে পারে। আমি আমার কোডটিতে অন্য কোনও উত্সাহী আনার প্রকারটি দেখছি না।
স্টিভ কুও 20'09

তারপরে আমার পরামর্শটি হ'ল এটি হ্রাস করার একটি সাধারণ উদাহরণ যা আপনি যা দেখছেন তা করে এবং যা পোস্ট করে তা পোস্ট করে। আপনার মডেলটিতে অন্যান্য জটিলতাও থাকতে পারে যা অপ্রত্যাশিত আচরণের কারণ হয়ে দাঁড়িয়েছে।
ক্লিটাস

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