যেহেতু এটি একটি খুব সাধারণ প্রশ্ন, আমি এই নিবন্ধটি লিখেছি
, যার ভিত্তিতে এই উত্তরটি ভিত্তিক।
সত্তা রাজ্য
জেপিএ নিম্নলিখিত সংস্থাগুলির সংজ্ঞা দেয়:
নতুন (ক্ষণস্থায়ী)
একটি সদ্য নির্মিত বস্তু যা হাইবারনেট Session
(ওরফে Persistence Context
) এর সাথে কখনও যুক্ত হয় নি এবং কোনও ডাটাবেস টেবিল সারিতে ম্যাপ করা হয়নি তা নতুন (ক্ষণস্থায়ী) অবস্থায় বিবেচিত হয়।
অবিচল থাকার জন্য আমাদের হয় স্পষ্টভাবে EntityManager#persist
পদ্ধতিটি কল করতে হবে বা ট্রানজিটিভ অধ্যবসায়ের প্রক্রিয়াটি ব্যবহার করতে হবে।
অবিরাম (পরিচালিত)
একটি অবিচলিত সত্তা একটি ডাটাবেস টেবিল সারিটির সাথে যুক্ত হয়েছে এবং এটি বর্তমানে চলমান দৃistence়প্রতিনিধি দ্বারা পরিচালিত হচ্ছে। এই জাতীয় সত্তায় যে কোনও পরিবর্তন করা হয়েছে তা সনাক্ত করে ডেটাবেজে প্রচার করা হচ্ছে (সেশন ফ্লাশ-সময় চলাকালীন)।
হাইবারনেট সহ, আমাদের আর ইনসার্ট / আপডেট / বিবৃতি মুছে ফেলতে হবে না। হাইবারনেট একটি লেনদেনমূলক রাইট-ব্যাক ওয়ার্কিং স্টাইলকে নিয়োগ করে এবং পরিবর্তনগুলি খুব শেষ দায়ী মুহুর্তে, বর্তমান Session
ফ্লাশ-সময়ের সময়ে সিঙ্ক্রোনাইজ করা হয় ।
বিচ্ছিন্ন
একবার চলমান দৃistence়প্রত্যক্ষ প্রসঙ্গটি বন্ধ হয়ে গেলে পূর্ববর্তী সমস্ত পরিচালিত সত্তা বিচ্ছিন্ন হয়ে যায়। ধারাবাহিক পরিবর্তনগুলি আর ট্র্যাক করা হবে না এবং কোনও স্বয়ংক্রিয় ডাটাবেস সিঙ্ক্রোনাইজেশন ঘটবে না।
সত্তার রাষ্ট্রের রূপান্তর
আপনি EntityManager
ইন্টারফেস দ্বারা সংজ্ঞায়িত বিভিন্ন পদ্ধতি ব্যবহার করে সত্তার স্থিতি পরিবর্তন করতে পারেন ।
জেপিএ সত্তা রাষ্ট্রের রূপান্তরগুলি আরও ভালভাবে বুঝতে, নিম্নলিখিত চিত্রটি বিবেচনা করুন:
জেপিএ ব্যবহার করার সময়, কোনও সক্রিয়কে পৃথক পৃথক সত্তাকে পুনঃস্থাপন EntityManager
করতে, আপনি মার্জ অপারেশনটি ব্যবহার করতে পারেন ।
নেটিভ হাইবারনেট এপিআই ব্যবহার merge
করার সময়, নীচের চিত্র দ্বারা প্রদর্শিত হিসাবে আপনি আপডেট পদ্ধতিগুলি ব্যবহার করে একটি সক্রিয় হাইবারনেট সেশনে একটি বিচ্ছিন্ন সত্তাকে পুনরায় সংযুক্ত করতে পারেন:
একটি বিচ্ছিন্ন সত্তা মার্জ করা
মার্জটি বিচ্ছিন্ন সত্তা রাষ্ট্রের (উত্স) একটি পরিচালিত সত্তা উদাহরণ (গন্তব্য) অনুলিপি করতে চলেছে।
বিবেচনা করুন আমরা নিম্নলিখিত Book
সত্তাকে অবিচলিত করেছি, এবং EntityManager
সত্তাটি বন্ধ হয়ে যাওয়ার জন্য ব্যবহার করা হয়েছিল বলে এখন সত্তাটি আলাদা করা হয়েছে :
Book _book = doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
entityManager.persist(book);
return book;
});
সত্তাটি বিচ্ছিন্ন অবস্থায় থাকা অবস্থায়, আমরা এটিকে নিম্নরূপে সংশোধন করি:
_book.setTitle(
"High-Performance Java Persistence, 2nd edition"
);
এখন, আমরা ডাটাবেসে পরিবর্তনগুলি প্রচার করতে চাই, সুতরাং আমরা merge
পদ্ধতিটি কল করতে পারি :
doInJPA(entityManager -> {
Book book = entityManager.merge(_book);
LOGGER.info("Merging the Book entity");
assertFalse(book == _book);
});
এবং হাইবারনেট নিম্নলিখিত এসকিউএল স্টেটমেন্টগুলি কার্যকর করতে চলেছে:
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
যদি মার্জিং সত্তাটির বর্তমানের কোনও সমতুল্য না থাকে EntityManager
তবে ডাটাবেস থেকে একটি নতুন সত্তার স্ন্যাপশট নেওয়া হবে।
একবার কোনও ম্যানেজড সত্তা থাকলে, জেপিএ বিচ্ছিন্ন সত্তার অবস্থার অনুলিপিটি বর্তমানে পরিচালিত একটিতে অনুলিপি করে এবং দৃ the ়তা প্রসঙ্গেflush
, যদি কোনও নোংরা চেকিংয়ের ব্যবস্থাটি খুঁজে পায় যে পরিচালিত সত্তাটি পরিবর্তিত হয়েছে।
সুতরাং, ব্যবহার করার সময় merge
, বিচ্ছিন্ন অবজেক্ট উদাহরণটি মার্জ ক্রিয়াকলাপের পরেও বিচ্ছিন্ন থাকা অবিরত থাকবে।
একটি বিচ্ছিন্ন সত্তা আবার পাঠাচ্ছে
হাইবারনেট, তবে জেপিএ update
পদ্ধতিটির মাধ্যমে পুনঃনির্দেশকে সমর্থন করে না ।
একটি হাইবারনেট Session
একটি প্রদত্ত ডাটাবেস সারিটির জন্য কেবল একটি সত্তা অবজেক্টকে যুক্ত করতে পারে। কারণ পার্সিস্টন কনটেক্সট একটি ইন-মেমরি ক্যাশে (প্রথম স্তরের ক্যাশে) হিসাবে কাজ করে এবং কেবলমাত্র একটি মান (সত্তা) প্রদত্ত কী (সত্তার ধরণ এবং ডাটাবেস শনাক্তকারী) এর সাথে সম্পর্কিত।
বর্তমান হাইবারনেটের সাথে ইতিমধ্যে অন্য কোনও জেভিএম অবজেক্ট (একই ডেটাবেস সারিটির সাথে মিলছে) না থাকলে কেবলমাত্র সত্তা পুনরায় সংযুক্ত করা যায় Session
।
বিবেচনা করে আমরা Book
সত্তাকে অবিচল রেখেছি এবং সত্তাটি যখন Book
বিচ্ছিন্ন অবস্থায় ছিল তখন আমরা এটিকে সংশোধন করেছি :
Book _book = doInJPA(entityManager -> {
Book book = new Book()
.setIsbn("978-9730228236")
.setTitle("High-Performance Java Persistence")
.setAuthor("Vlad Mihalcea");
entityManager.persist(book);
return book;
});
_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");
});
এবং হাইবারনেট নিম্নলিখিত এসকিউএল বিবৃতি কার্যকর করবে:
-- Updating the Book entity
UPDATE
book
SET
author = 'Vlad Mihalcea',
isbn = '978-9730228236',
title = 'High-Performance Java Persistence, 2nd edition'
WHERE
id = 1
update
পদ্ধতি করতে হবে একটি হাইবারনেট করতে ।unwrap
EntityManager
Session
বিপরীতে merge
, সরবরাহিত বিচ্ছিন্ন সত্তাটি বর্তমান দৃ Pers়তা প্রসঙ্গে পুনরায় যোগাযোগ করতে চলেছে এবং সত্তাটি পরিবর্তন করেছে কিনা তা ফ্লাশ চলাকালীন একটি আপডেটের সময়সূচী রয়েছে।
এটি প্রতিরোধ করতে, আপনি @SelectBeforeUpdate
হাইবারনেট টীকাগুলি ব্যবহার করতে পারেন যা এমন একটি নির্বাচনী বিবৃতি ট্রিগার করবে যা লোড হওয়া অবস্থায় আনবে যা পরে নোংরা চেকিং প্রক্রিয়া দ্বারা ব্যবহৃত হয়।
@Entity(name = "Book")
@Table(name = "book")
@SelectBeforeUpdate
public class Book {
//Code omitted for brevity
}
ননউইনিকউজেক্টএক্সসেপশন থেকে সাবধান থাকুন
একটি সমস্যা যা ঘটতে পারে update
তা হ'ল যদি দৃistence়তা প্রসঙ্গে ইতিমধ্যে একই আইডির সাথে সত্তার রেফারেন্স থাকে এবং নিম্নলিখিত উদাহরণের মতো একই ধরণের:
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)
উপসংহার
merge
পদ্ধতি যদি আপনি আশাবাদী লকিং ব্যবহার করছেন যেমন আপনি হারিয়ে আপডেটগুলি যাতে করার অনুমতি দেয় অগ্রাধিকার হয়। এই বিষয় সম্পর্কে আরও তথ্যের জন্য, এই নিবন্ধটি দেখুন ।
update
যেমন অতিরিক্ত SELECT স্টেটমেন্ট দ্বারা উত্পন্ন প্রতিরোধ করতে পারি ব্যাচ আপডেট জন্য ভাল merge
অপারেশন, অতএব ব্যাচ আপডেট সঞ্চালনের সময় কমে যায়।
refresh()
বিচ্ছিন্ন সত্তাগুলি অনুমতি দেয় না এমন কোনও কারণ আছে কি ? ২.০ অনুমানের মধ্যে দিয়ে আমি কোনও ন্যায়সঙ্গত দেখতে পাচ্ছি না; এটি অনুমোদিত নয়।