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

হাইবারনেট Sessionসমস্ত জেপিএ EntityManagerপদ্ধতি প্রয়োগ করে এবং কিছু অতিরিক্ত সত্তা রাষ্ট্রের রূপান্তর পদ্ধতি যেমন save, saveOrUpdateএবং সরবরাহ করে update।

জিদ করা
অস্থায়ী (নতুন) থেকে পরিচালিত (বহিরাগত) এ সত্তার অবস্থার পরিবর্তন করতে আমরা ব্যবহার করতে পারি persist জেপিএ দ্বারা প্রদত্ত পদ্ধতিটিEntityManager যা হাইবারনেট দ্বারা উত্তরাধিকার সূত্রে প্রাপ্ত Session।
persistপদ্ধতি ট্রিগার একটিPersistEvent যার দ্বারা পরিচালিত হয় DefaultPersistEventListenerহাইবারনেট ঘটনা শ্রোতা।
অতএব, নিম্নলিখিত পরীক্ষার কেসটি কার্যকর করার সময়:
doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
entityManager.persist(book);
LOGGER.info(
"Persisting the Book entity with the id: {}",
book.getId()
);
});
হাইবারনেট নিম্নলিখিত এসকিউএল বিবৃতি উত্পন্ন করে:
CALL NEXT VALUE FOR hibernate_sequence
-- Persisting the Book entity with the id: 1
INSERT INTO book (
author,
isbn,
title,
id
)
VALUES (
'Vlad Mihalcea',
'978-9730228236',
'High-Performance Java Persistence',
1
)
লক্ষ্য করুন যে বর্তমান অধ্যবসায় প্রসঙ্গে সত্তা idসংযুক্ত করার আগে নিয়োগ করা হয়েছে Book। এটির প্রয়োজন হয় কারণ পরিচালিত সত্তাগুলি একটিতে সংরক্ষণ করা হয়Map কাঠামোতে যেখানে কীটি সত্তার প্রকার এবং তার শনাক্তকারী দ্বারা তৈরি করা হয় এবং মানটি সত্তা রেফারেন্স। এই কারণেই জেপিএ EntityManagerএবং হাইবারনেট Sessionপ্রথম-স্তরের ক্যাশে হিসাবে পরিচিত।
কল করার সময় persist , সত্তাটি কেবল বর্তমানে চলমান পার্সিস্টান প্রসঙ্গে যুক্ত থাকে এবং INSERT flushডাকা না হওয়া পর্যন্ত স্থগিত করা যায় ।
একমাত্র ব্যতিক্রম হ'ল পরিচয় জেনারেটর যা এই মুহুর্তে সন্নিবেশটিকে ট্রিগার করে যেহেতু সত্তা সনাক্তকারী হিসাবে এটি পাওয়া যায় way এই কারণে, হাইবারনেট পরিচয় জেনারেটর ব্যবহার করে সত্তার জন্য সন্নিবেশগুলি ব্যাচ করতে পারে না। এই বিষয় সম্পর্কে আরও তথ্যের জন্য, চেক আউট এই নিবন্ধটি দেখুন ।
সংরক্ষণ
হাইবারনেট-নির্দিষ্ট save পদ্ধতিটি জেপিএর পূর্বাভাস দেয় এবং হাইবারনেট প্রকল্পের শুরু থেকেই এটি উপলব্ধ।
saveপদ্ধতি আরম্ভ করে SaveOrUpdateEventযার দ্বারা পরিচালিত হয় DefaultSaveOrUpdateEventListenerহাইবারনেট ঘটনা শ্রোতা। অতএব, saveপদ্ধতি সমতূল্য updateএবংsaveOrUpdate পদ্ধতির ।
saveপদ্ধতিটি কীভাবে কাজ করে তা দেখতে নিম্নলিখিত পরীক্ষার ক্ষেত্রে বিবেচনা করুন:
doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
Session session = entityManager.unwrap(Session.class);
Long id = (Long) session.save(book);
LOGGER.info(
"Saving the Book entity with the id: {}",
id
);
});
উপরের পরীক্ষার কেসটি চালানোর সময় হাইবারনেট নিম্নলিখিত এসকিউএল বিবৃতি উত্পন্ন করে:
CALL NEXT VALUE FOR hibernate_sequence
-- Saving the Book entity with the id: 1
INSERT INTO book (
author,
isbn,
title,
id
)
VALUES (
'Vlad Mihalcea',
'978-9730228236',
'High-Performance Java Persistence',
1
)
আপনি দেখতে পাচ্ছেন, ফলাফলটি persistপদ্ধতি কলের মতো ident তবে, অসদৃশ persist,save পদ্ধতিটি সত্তা শনাক্তকারীকে দেয়।
আরও তথ্যের জন্য, এই নিবন্ধটি দেখুন ।
হালনাগাদ
হাইবারনেট-নির্দিষ্ট updateপদ্ধতিটি বোঝানো হচ্ছে নোংরা চেকিং মেকানিজমকে বাইপাস করা এবং ফ্লাশের সময় কোনও সত্তা আপডেট জোর করে।
updateপদ্ধতি আরম্ভ করে SaveOrUpdateEventযার দ্বারা পরিচালিত হয় DefaultSaveOrUpdateEventListenerহাইবারনেট ঘটনা শ্রোতা। সুতরাং, updateপদ্ধতিটি saveএবংsaveOrUpdate পদ্ধতির সমান ।
updateপদ্ধতিটি কীভাবে কাজ করে তা নীচের উদাহরণটিকে বিবেচনা করে যা কোনও Bookলেনদেনে সত্তা অব্যাহত রাখে , তারপরে সত্তাটি বিচ্ছিন্ন অবস্থায় থাকা অবস্থায় এটি সংশোধন করে এবং updateপদ্ধতি কলটি ব্যবহার করে এটি এসকিউএল আপডেটের দিকে বাধ্য করে ।
Book _book = doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
entityManager.persist(book);
return book;
});
LOGGER.info("Modifying the Book entity");
_book.setTitle(
"High-Performance Java Persistence, 2nd edition"
);
doInJPA(entityManager -> {
Session session = entityManager.unwrap(Session.class);
session.update(_book);
LOGGER.info("Updating the Book entity");
});
উপরের পরীক্ষার কেসটি কার্যকর করার সময় হাইবারনেট নিম্নলিখিত এসকিউএল বিবৃতি উত্পন্ন করে:
CALL NEXT VALUE FOR hibernate_sequence
INSERT INTO book (
author,
isbn,
title,
id
)
VALUES (
'Vlad Mihalcea',
'978-9730228236',
'High-Performance Java Persistence',
1
)
-- Modifying the Book entity
-- Updating the Book entity
UPDATE
book
SET
author = 'Vlad Mihalcea',
isbn = '978-9730228236',
title = 'High-Performance Java Persistence, 2nd edition'
WHERE
id = 1
লক্ষ্য করুন যে প্রতিশ্রুতি দেওয়ার UPDATEঠিক পূর্বে দৃistence়তা কনটেক্সট ফ্লাশ চলাকালীন মৃত্যুদন্ড কার্যকর করা হয়েছিল এবং সে কারণেইUpdating the Book entity বার্তাটি প্রথমে লগ হয়।
ব্যবহার @SelectBeforeUpdateঅপ্রয়োজনীয় আপডেটগুলি এড়াতে করা
এখন, আপডেট আপডেট সর্বদা কার্যকর করা হবে এমনকি সত্তাটি বিচ্ছিন্ন অবস্থায় থাকা অবস্থায় পরিবর্তিত না হলেও। এটি প্রতিরোধ করতে, আপনি @SelectBeforeUpdateহাইবারনেট টীকাগুলি ব্যবহার করতে পারেন যা একটি SELECTবিবৃতি ট্রিগার করবে loaded stateযা পরে নোংরা চেকিং প্রক্রিয়া দ্বারা ব্যবহৃত হয়।
সুতরাং, আমরা যদি টীকাটি Bookদিয়ে সত্তাটি @SelectBeforeUpdateটীকায়িত করি:
@Entity(name = "Book")
@Table(name = "book")
@SelectBeforeUpdate
public class Book {
//Code omitted for brevity
}
এবং নিম্নলিখিত পরীক্ষার কেস কার্যকর করুন:
Book _book = doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
entityManager.persist(book);
return book;
});
doInJPA(entityManager -> {
Session session = entityManager.unwrap(Session.class);
session.update(_book);
});
হাইবারনেট নিম্নলিখিত এসকিউএল স্টেটমেন্টগুলি সম্পাদন করে:
INSERT INTO book (
author,
isbn,
title,
id
)
VALUES (
'Vlad Mihalcea',
'978-9730228236',
'High-Performance Java Persistence',
1
)
SELECT
b.id,
b.author AS author2_0_,
b.isbn AS isbn3_0_,
b.title AS title4_0_
FROM
book b
WHERE
b.id = 1
লক্ষ্য করুন যে, UPDATEহাইবারনেট নোংরা চেকিং প্রক্রিয়াটি আবিষ্কার করেছে যে সত্তাটি পরিবর্তন করা হয়নি since
SaveOrUpdate
হাইবারনেট-নির্দিষ্ট saveOrUpdateপদ্ধতিটি কেবলমাত্র একটি উপনাম saveএবং এর জন্য update।
saveOrUpdateপদ্ধতি আরম্ভ করে SaveOrUpdateEventযার দ্বারা পরিচালিত হয় DefaultSaveOrUpdateEventListenerহাইবারনেট ঘটনা শ্রোতা। সুতরাং, updateপদ্ধতিটি saveএবংsaveOrUpdate পদ্ধতির সমান ।
এখন, আপনি saveOrUpdateযখন কোনও সত্তাকে অবিচল থাকতে চান বা UPDATEনীচের উদাহরণ দ্বারা চিত্রিত হিসাবে জোর করতে চান তখন আপনি ব্যবহার করতে পারেন ।
Book _book = doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
Session session = entityManager.unwrap(Session.class);
session.saveOrUpdate(book);
return book;
});
_book.setTitle("High-Performance Java Persistence, 2nd edition");
doInJPA(entityManager -> {
Session session = entityManager.unwrap(Session.class);
session.saveOrUpdate(_book);
});
সাবধান NonUniqueObjectException
একটা সমস্যা যে সঙ্গে ঘটতে পারে save, updateএবং saveOrUpdateযদি অধ্যবসায় প্রসঙ্গ ইতিমধ্যে একই আইডি-র এবং নিম্নলিখিত উদাহরণ হিসাবে একই ধরণের একটি সত্তা রেফারেন্স রয়েছে:
Book _book = doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
Session session = entityManager.unwrap(Session.class);
session.saveOrUpdate(book);
return book;
});
_book.setTitle(
"High-Performance Java Persistence, 2nd edition"
);
try {
doInJPA(entityManager -> {
Book book = entityManager.find(
Book.class,
_book.getId()
);
Session session = entityManager.unwrap(Session.class);
session.saveOrUpdate(_book);
});
} catch (NonUniqueObjectException e) {
LOGGER.error(
"The Persistence Context cannot hold " +
"two representations of the same entity",
e
);
}
এখন, উপরোক্ত পরীক্ষার কেসটি কার্যকর করার সময়, হাইবারনেট একটি নিক্ষেপ করতে চলেছে NonUniqueObjectExceptionকারণ দ্বিতীয়টিতে EntityManagerইতিমধ্যে Bookএকই শনাক্তকারীর সাথে একটি সত্তা রয়েছে যা আমরা পাস করেছি updateএবং পার্সিস্টি কনটেক্সট একই সত্তার দুটি উপস্থাপনা রাখতে পারে না।
org.hibernate.NonUniqueObjectException:
A different object with the same identifier value was already associated with the session : [com.vladmihalcea.book.hpjp.hibernate.pc.Book#1]
at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:651)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:227)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:92)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:682)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:674)
একত্রিত করা
এড়াতে NonUniqueObjectException, আপনাকে mergeজেপিএ দ্বারা প্রদত্ত পদ্ধতিটি EntityManagerএবং হাইবারনেট দ্বারা উত্তরাধিকারসূত্রেও ব্যবহার Sessionকরা উচিত।
এই নিবন্ধে বর্ণিত হিসাবে , mergeপার্সিস্ট্যান্স প্রসঙ্গে যদি কোনও সত্তার রেফারেন্স না পাওয়া যায় তবে এটি ডাটাবেস থেকে একটি নতুন সত্তার স্ন্যাপশট নিয়ে আসে এবং এটি mergeপদ্ধতিতে পাস হওয়া বিচ্ছিন্ন সত্তার অবস্থার অনুলিপি করে ।
mergeপদ্ধতি আরম্ভ করেMergeEvent যার দ্বারা পরিচালিত হয় DefaultMergeEventListenerহাইবারনেট ঘটনা শ্রোতা।
mergeপদ্ধতিটি কীভাবে কাজ করে তা নীচের উদাহরণটিকে বিবেচনা করে যা কোনও Bookলেনদেনে সত্তা অব্যাহত থাকে , তারপরে সত্তাটি বিচ্ছিন্ন অবস্থায় থাকা অবস্থায় এটি সংশোধন করে এবং বিচ্ছিন্ন অস্তিত্বটিকে mergeএকটি পরের দৃistence়তা প্রসঙ্গে পাঠায়।
Book _book = doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
entityManager.persist(book);
return book;
});
LOGGER.info("Modifying the Book entity");
_book.setTitle(
"High-Performance Java Persistence, 2nd edition"
);
doInJPA(entityManager -> {
Book book = entityManager.merge(_book);
LOGGER.info("Merging the Book entity");
assertFalse(book == _book);
});
উপরোক্ত পরীক্ষার মামলাটি চালানোর সময়, হাইবারনেট নিম্নলিখিত এসকিউএল বিবৃতি কার্যকর করে:
INSERT INTO book (
author,
isbn,
title,
id
)
VALUES (
'Vlad Mihalcea',
'978-9730228236',
'High-Performance Java Persistence',
1
)
-- Modifying the Book entity
SELECT
b.id,
b.author AS author2_0_,
b.isbn AS isbn3_0_,
b.title AS title4_0_
FROM
book b
WHERE
b.id = 1
-- Merging the Book entity
UPDATE
book
SET
author = 'Vlad Mihalcea',
isbn = '978-9730228236',
title = 'High-Performance Java Persistence, 2nd edition'
WHERE
id = 1
লক্ষ্য করুন যে সত্তার রেফারেন্সটি mergeদিয়ে দেওয়া হয়েছে তা mergeপদ্ধতিটিতে আমরা যে আলাদা করেছি তার চেয়ে আলাদা ।
এখন, যদিও mergeবিচ্ছিন্ন সত্তার স্থিতি অনুলিপি করার সময় আপনার জেপিএ ব্যবহার পছন্দ করা উচিত, তবুও SELECTব্যাচ প্রসেসিংয়ের কার্য সম্পাদন করার সময় অতিরিক্ত সমস্যা হতে পারে।
এই কারণে, আপনার ব্যবহার পছন্দ করা উচিত update যখন আপনি নিশ্চিত হন যে ইতিমধ্যে চলমান দৃ .়পদ প্রসঙ্গে ইতিমধ্যে কোনও সত্তা রেফারেন্স সংযুক্ত নেই এবং পৃথক পৃথক উপাদানটি সংশোধন করা হয়েছে।
এই বিষয় সম্পর্কে আরও তথ্যের জন্য, এই নিবন্ধটি দেখুন ।
উপসংহার
কোনও সত্তা অবিরত রাখতে, আপনার জেপিএ persistপদ্ধতিটি ব্যবহার করা উচিত । বিচ্ছিন্ন সত্তা রাষ্ট্র অনুলিপি করতে, mergeপছন্দ করা উচিত। updateপদ্ধতি ব্যাচ প্রসেসিং কর্ম শুধুমাত্র দরকারী। saveএবং saveOrUpdateমাত্র alias লেখা হয় updateএবং আপনি সম্ভবত সব সময়ে তাদের ব্যবহার করা উচিত নয়।
saveসত্তা ইতিমধ্যে পরিচালনা করা হলেও কিছু বিকাশকারী কল করে , কিন্তু এটি একটি ভুল এবং পরিচালিত সংস্থাগুলির জন্য, আপডেটটি স্বয়ংক্রিয়ভাবে পার্সিটি কনটেক্স ফ্ল্যাশ সময় পরিচালিত হয়।
আরও তথ্যের জন্য, এই নিবন্ধটি দেখুন ।