আমি জাভা পার্সিটিশন এপিআই এবং হাইবারনেট এর নবাগত।
জাভা পার্সেন্টিপি এপিআই FetchType.LAZY
এবং এর FetchType.EAGER
মধ্যে পার্থক্য কী ?
আমি জাভা পার্সিটিশন এপিআই এবং হাইবারনেট এর নবাগত।
জাভা পার্সেন্টিপি এপিআই FetchType.LAZY
এবং এর FetchType.EAGER
মধ্যে পার্থক্য কী ?
উত্তর:
কখনও কখনও আপনার দুটি সত্তা থাকে এবং তাদের মধ্যে একটি সম্পর্ক রয়েছে। উদাহরণস্বরূপ, আপনার কাছে একটি সত্ত্বা বলা হতে পারে University
এবং অন্য একটি সত্ত্বা বলা Student
হতে পারে এবং একটি বিশ্ববিদ্যালয়ের অনেক শিক্ষার্থী থাকতে পারে:
বিশ্ববিদ্যালয় সত্তার কিছু প্রাথমিক বৈশিষ্ট্য থাকতে পারে যেমন আইডি, নাম, ঠিকানা ইত্যাদি well পাশাপাশি একটি শিক্ষার্থী নামে একটি সংগ্রহ সম্পত্তি যা একটি প্রদত্ত বিশ্ববিদ্যালয়ের শিক্ষার্থীদের তালিকা ফিরিয়ে দেয়:
public class University {
private String id;
private String name;
private String address;
private List<Student> students;
// setters and getters
}
এখন আপনি যখন ডাটাবেস থেকে কোনও বিশ্ববিদ্যালয় লোড করেন, জেপিএ আপনার আইডি, নাম এবং ঠিকানা ক্ষেত্রগুলি লোড করে। তবে কীভাবে শিক্ষার্থীদের বোঝাই করা উচিত তার জন্য আপনার কাছে দুটি বিকল্প রয়েছে:
getStudents()
পদ্ধতিটি কল করার সময় এটি অন-ডিমান্ডে (অর্থাত্ অলসভাবে) লোড করতে ।যখন কোনও বিশ্ববিদ্যালয়ে অনেক শিক্ষার্থী থাকে তখন এটির সাথে তার সমস্ত ছাত্রকে একসাথে লোড করা দক্ষ নয়, বিশেষত যখন তাদের প্রয়োজন হয় না এবং এ জাতীয় ক্ষেত্রে আপনি ঘোষণা করতে পারেন যে শিক্ষার্থীরা যখন প্রয়োজন হয় তখন তাদের বোঝা করা উচিত। একে অলস লোডিং বলা হয়।
এখানে একটি উদাহরণ দেওয়া হয়েছে, যেখানে students
স্পষ্টভাবে আগ্রহীভাবে লোড হওয়ার জন্য চিহ্নিত করা হয়েছে:
@Entity
public class University {
@Id
private String id;
private String name;
private String address;
@OneToMany(fetch = FetchType.EAGER)
private List<Student> students;
// etc.
}
এবং এখানে একটি উদাহরণ রয়েছে যেখানে students
সুস্পষ্টভাবে অলসভাবে লোড হওয়ার জন্য চিহ্নিত করা হয়েছে:
@Entity
public class University {
@Id
private String id;
private String name;
private String address;
@OneToMany(fetch = FetchType.LAZY)
private List<Student> students;
// etc.
}
getStudents()
) দিয়ে মেমোরিতে লোড করতে চায় তবে কখনও কখনও এটি সম্ভব হয় না, কারণ সময়কালে এই পদ্ধতিটি বলা হয়, অধিবেশনটি ইতিমধ্যে বন্ধ হয়ে গেছে এবং সত্তাটি আলাদা করা হয়েছে। একইভাবে, কখনও কখনও আমাদের কাছে ক্লায়েন্ট / সার্ভারের আর্কিটেকচার থাকে (যেমন সুইং ক্লায়েন্ট / জেইই সার্ভার) এবং সত্ত্বা / ডিটিওগুলি তারের উপর দিয়ে ক্লায়েন্টে স্থানান্তরিত হয় এবং প্রায়শই প্রায়শই এই পরিস্থিতিতে অলস লোডিং সত্ত্বার উপায়ের কারণে কাজ করবে না work তারের উপর সিরিয়ালযুক্ত হয়।
getStudents()
প্রথমবারের মতো পদ্ধতিটি কল করি তখন ফলাফলগুলি ক্যাশেড হয়? যাতে আমি পরের বারে এই ফলাফলগুলি অ্যাক্সেস করতে পারি?
মূলত,
LAZY = fetch when needed
EAGER = fetch immediately
EAGER
সংগ্রহগুলি লোড করার অর্থ তাদের পিতামাতাকে আনার সময় এগুলি পুরোপুরি আনা হয়। তাই আপনি যদি আপনার আছে Course
এবং এটা আছে List<Student>
, সব ছাত্র নিয়ে আসা হয় ডাটাবেস থেকে সময়ে Course
পেয়েছে।
LAZY
অন্যদিকে এর অর্থ হ'ল List
যখন আপনি সেগুলিতে অ্যাক্সেস করার চেষ্টা করবেন তখনই এর সামগ্রীগুলি আনবে। উদাহরণস্বরূপ, কল করে course.getStudents().iterator()
। যে কোনও অ্যাক্সেস পদ্ধতিতে List
কল করা উপাদানগুলি পুনরুদ্ধার করতে ডাটাবেসে একটি কল শুরু করবে। এটি List
(বা Set
) এর আশেপাশে একটি প্রক্সি তৈরি করে প্রয়োগ করা হয় । সুতরাং আপনার অলস সংগ্রহের জন্য, কংক্রিটের ধরণগুলি নয় ArrayList
এবং HashSet
, PersistentSet
এবং এবং PersistentList
(বা PersistentBag
)
course.getStudents()
, এটি একটি এসকিউএল কোয়েরি চালিত করে (এটি কনসোলটিতে দেখেছিল)। অলস আনার প্রকারেও একই ঘটনা ঘটে। তো, পার্থক্য কি ??
fetchtype = LAZY
ডিফল্টরূপে সেট করা হয় এমনকি গিটার হাইবারনেট দিয়ে সংগ্রহ করার চেষ্টা করেও আমাকে মূল্যায়ন করতে পারে না বলে বলছে
আমি কর্মক্ষমতা এবং মেমরির ব্যবহার বিবেচনা করতে পারি। একটি বড় পার্থক্য হ'ল ইগ্রার আনার কৌশলটি সেশন ছাড়াই আনীত ডেটা অবজেক্টটি ব্যবহার করতে দেয়। কেন?
সেশনটি সংযুক্ত থাকাকালীন বস্তুটিতে আগ্রহী চিহ্নিত ডেটা যখন সমস্ত ডেটা আনয়ন করা হয়। যাইহোক, অলস লোডিং কৌশলের ক্ষেত্রে অলস লোডিং চিহ্নিত বস্তুটি সেশনটি সংযোগ বিচ্ছিন্ন হয়ে গেলে ( session.close()
বিবৃতি দেওয়ার পরে ) ডেটা পুনরুদ্ধার করে না । হাইবারনেট প্রক্সি দিয়ে তৈরি করা যেতে পারে। আগ্রহী কৌশলটি অধিবেশন বন্ধ করার পরে ডেটা এখনও উপলভ্য হতে দেয়।
ডিফল্টরূপে, সমস্ত সংগ্রহ এবং মানচিত্রের অবজেক্টের জন্য আনার নিয়ম FetchType.LAZY
এবং অন্যান্য দৃষ্টান্তে এটি FetchType.EAGER
নীতি অনুসরণ করে ।
সংক্ষেপে, @OneToMany
এবং @ManyToMany
সম্পর্কগুলি সম্পর্কিত বিষয়গুলি (সংগ্রহ এবং মানচিত্র) জড়িতভাবে আনে না তবে পুনরুদ্ধার অপারেশনটি ক্ষেত্রের মধ্যে @OneToOne
এবং এর মধ্যে ক্যাসকেড করা হয় @ManyToOne
।
উভয় FetchType.LAZY
এবং ডিফল্ট আনয়ন পরিকল্পনাFetchType.EAGER
সংজ্ঞায়িত করতে ব্যবহৃত হয় ।
দুর্ভাগ্যক্রমে, আপনি কেবল অলস সংগ্রহের জন্য ডিফল্ট আনার পরিকল্পনাটিকে ওভাররাইড করতে পারেন। ইগ্রার আনতে কম নমনীয় হয় এবং অনেকগুলি কার্য সম্পাদনের সমস্যার কারণ হতে পারে ।
আমার পরামর্শ হ'ল আপনার সমিতিগুলিকে ইগ্রার করার তাগিদকে প্রতিরোধ করা কারণ আনয়ন একটি প্রশ্ন-সময় দায়িত্ব। সুতরাং আপনার সমস্ত প্রশ্নের ক্ষেত্রে কেবলমাত্র বর্তমান ব্যবসায়িক ক্ষেত্রে প্রয়োজনীয় তা পুনরুদ্ধার করতে আনতে নির্দেশিকা ব্যবহার করা উচিত ।
জাভাডোক থেকে :
EAGER কৌশলটি দৃ pers়তা সরবরাহকারীর রানটাইমের একটি প্রয়োজনীয়তা যা ডেটা আগ্রহের সাথে আনতে হবে। অলস কৌশলটি অধ্যবসায় সরবরাহকারী রানটাইমের প্রতি ইঙ্গিত দেয় যে ডেটা যখন প্রথম অ্যাক্সেস করা হয় তখন আলস্যভাবে আনা উচিত।
যেমন, উত্সাহী অলস চেয়ে বেশি সক্রিয়। অলস কেবল প্রথম ব্যবহারে ঘটে (যদি সরবরাহকারী ইঙ্গিতটি নেয়) তবে আগ্রহী জিনিসগুলির সাথে (হয়ত) প্রাক-আনতে পারে।
Lazy
পান টাইপ হাইবারনেট দ্বারা নির্বাচিত, যদি না আপনি স্পষ্টভাবে চিহ্নিত ডিফল্টরূপে হয় Eager
টাইপ পান। আরও নির্ভুল এবং সংক্ষিপ্ত হওয়ার জন্য, পার্থক্যটি নীচে হিসাবে বর্ণনা করা যেতে পারে।
FetchType.LAZY
= যদি আপনি গেটর পদ্ধতির মাধ্যমে এটি না চান তবে এটি সম্পর্ক লোড করে না।
FetchType.EAGER
= এটি সমস্ত সম্পর্ক লোড করে।
এই দুটি আনার ধরণের প্রো এবং কনস Cons
Lazy initialization
অপ্রয়োজনীয় গণনা এড়িয়ে মেমরির প্রয়োজনীয়তাগুলি হ্রাস করে কর্মক্ষমতা উন্নত করে।
Eager initialization
আরও মেমরি খরচ লাগে এবং প্রক্রিয়াকরণের গতি ধীর হয়।
এই কথাটি বলার পরে, পরিস্থিতির উপর নির্ভর করে যে কোনও একটি এই আরম্ভের ব্যবহার করা যেতে পারে।
getMember
যেটি সেই সদস্যের নামের ধরণটির সাথে সঠিকভাবে মেলে?
Book.java
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="Books")
public class Books implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="book_id")
private int id;
@Column(name="book_name")
private String name;
@Column(name="author_name")
private String authorName;
@ManyToOne
Subject subject;
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
}
Subject.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="Subject")
public class Subject implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="subject_id")
private int id;
@Column(name="subject_name")
private String name;
/**
Observe carefully i have mentioned fetchType.EAGER. By default its is fetchType.LAZY for @OneToMany i have mentioned it but not required. Check the Output by changing it to fetchType.EAGER
*/
@OneToMany(mappedBy="subject",cascade=CascadeType.ALL,fetch=FetchType.LAZY,
orphanRemoval=true)
List<Books> listBooks=new ArrayList<Books>();
public List<Books> getListBooks() {
return listBooks;
}
public void setListBooks(List<Books> listBooks) {
this.listBooks = listBooks;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
HibernateUtil.java
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory ;
static {
Configuration configuration = new Configuration();
configuration.addAnnotatedClass (Com.OneToMany.Books.class);
configuration.addAnnotatedClass (Com.OneToMany.Subject.class);
configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver");
configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");
configuration.setProperty("hibernate.connection.username", "root");
configuration.setProperty("hibernate.connection.password", "root");
configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
configuration.setProperty("hibernate.hbm2ddl.auto", "update");
configuration.setProperty("hibernate.show_sql", "true");
configuration.setProperty(" hibernate.connection.pool_size", "10");
configuration.setProperty(" hibernate.cache.use_second_level_cache", "true");
configuration.setProperty(" hibernate.cache.use_query_cache", "true");
configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider");
configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory");
// configuration
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Main.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory factory=HibernateUtil.getSessionFactory();
save(factory);
retrieve(factory);
}
private static void retrieve(SessionFactory factory) {
Session session=factory.openSession();
try{
session.getTransaction().begin();
Subject subject=(Subject)session.get(Subject.class, 1);
System.out.println("subject associated collection is loading lazily as @OneToMany is lazy loaded");
Books books=(Books)session.get(Books.class, 1);
System.out.println("books associated collection is loading eagerly as by default @ManyToOne is Eagerly loaded");
/*Books b1=(Books)session.get(Books.class, new Integer(1));
Subject sub=session.get(Subject.class, 1);
sub.getListBooks().remove(b1);
session.save(sub);
session.getTransaction().commit();*/
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
private static void save(SessionFactory factory){
Subject subject=new Subject();
subject.setName("C++");
Books books=new Books();
books.setAuthorName("Bala");
books.setName("C++ Book");
books.setSubject(subject);
subject.getListBooks().add(books);
Session session=factory.openSession();
try{
session.beginTransaction();
session.save(subject);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
}
মেইন.জাবার পুনরুদ্ধার () পদ্ধতিটি পরীক্ষা করে দেখুন। আমরা যখন বিষয় পেয়েই থাকে, তাহলে তার সংগ্রহে listBooks সঙ্গে সটীক @OneToMany
, প্রখর রৌদ্রে লোড হবে। কিন্তু অন্যদিকে, বই এর সাথে সম্পর্কিত সংগ্রহ সমিতি বিষয় , সঙ্গে সটীক @ManyToOne
, লোড eargerly (দ্বারা [default][1]
জন্য @ManyToOne
, fetchType=EAGER
)। আমরা সাবজেক্ট.জভাতে @OneToMany
ফেচটাইপ.এগ্রার বা বুকস.জাভাতে ফেচটাইপ.লাজেওয়াই রেখে আচরণটি পরিবর্তন করতে @ManyToOne
পারি।
পাবলিক এনাম ফেচটাইপ java.lang.Enum ডেটাবেস থেকে ডেটা আনার জন্য কৌশল নির্ধারণ করে। EAGER কৌশলটি দৃ pers়তা সরবরাহকারীর রানটাইমের একটি প্রয়োজনীয়তা যা ডেটা আগ্রহের সাথে আনতে হবে। অলস কৌশলটি অধ্যবসায় সরবরাহকারী রানটাইমের প্রতি ইঙ্গিত দেয় যে ডেটা যখন প্রথম অ্যাক্সেস করা হয় তখন আলস্যভাবে আনা উচিত। বাস্তবায়নের জন্য অধীর আগ্রহে ডেটা আনার অনুমতি দেওয়া হয়েছে যার জন্য অলস কৌশলটির ইঙ্গিতটি নির্দিষ্ট করা হয়েছে। উদাহরণ: @ বেসিক (ফেচ = এলজিওয়াই) সুরক্ষিত স্ট্রিং গেটনাম () {ফেরতের নাম; }
উপরে "কিউং হুয়ান মিন" যা বলেছে তাতে আমি এই নোটটি যুক্ত করতে চাই।
মনে করুন আপনি এই সাধারণ স্থপতিটির সাথে স্প্রিং রেস্ট ব্যবহার করছেন:
নিয়ামক <-> পরিষেবা <-> সংগ্রহস্থল
এবং আপনি সামনের প্রান্তে কিছু ডেটা ফিরিয়ে দিতে চান, আপনি যদি ব্যবহার করে থাকেন তবে আপনি FetchType.LAZY
নিয়ামক পদ্ধতিতে ডেটা ফিরিয়ে দেওয়ার পরে একটি ব্যতিক্রম পাবেন যেহেতু সেবায় সেশনটি বন্ধ রয়েছে তাই JSON Mapper Object
ডেটা পেতে না পারে।
এই সমস্যাটি সমাধান করার জন্য তিনটি সাধারণ বিকল্প রয়েছে, এটি নকশা, কর্মক্ষমতা এবং বিকাশকারী উপর নির্ভর করে:
FetchType.EAGER
, যাতে নিয়ন্ত্রক পদ্ধতিতে সেশনটি এখনও জীবিত থাকে।FetchType.LAZY
রূপান্তর পদ্ধতিতে ডেটা Entity
অন্য ডেটা অবজেক্টে স্থানান্তর করতে DTO
এবং এটি নিয়ামকের কাছে প্রেরণে ব্যবহার করা, সুতরাং সেশনটি বন্ধ হয়ে গেলে কোনও ব্যতিক্রম নেই।@ ড্রপ-শ্যাডো যদি আপনি হাইবারনেট ব্যবহার করেন তবে আপনি Hibernate.initialize()
যখন getStudents()
পদ্ধতিটি চালু করবেন তখন কল করতে পারবেন :
Public class UniversityDaoImpl extends GenericDaoHibernate<University, Integer> implements UniversityDao {
//...
@Override
public University get(final Integer id) {
Query query = getQuery("from University u where idUniversity=:id").setParameter("id", id).setMaxResults(1).setFetchSize(1);
University university = (University) query.uniqueResult();
***Hibernate.initialize(university.getStudents());***
return university;
}
//...
}
অলস: এটি সন্তানের সত্তা অলসভাবে আনে অর্থাত্ পিতামাতার সত্তা আনার সময় এটি কেবলমাত্র শিশু সত্তার প্রক্সি (সিগ্লিব বা অন্য কোনও ইউটিলিটি দ্বারা নির্মিত) আনে এবং যখন আপনি শিশু সত্তার কোনও সম্পত্তি অ্যাক্সেস করেন তবে এটি আসলে হাইবারনেট দ্বারা আনা হয়।
ইগর: এটি পিতামাতার সাথে সন্তানের সত্তাও নিয়ে আসে।
আরও ভাল বোঝার জন্য Jboss ডকুমেন্টেশনে যান বা আপনি hibernate.show_sql=true
আপনার অ্যাপ্লিকেশনটির জন্য ব্যবহার করতে পারেন এবং হাইবারনেট দ্বারা জারি করা অনুসন্ধানগুলি পরীক্ষা করতে পারেন ।