synchronizedজাভা কীওয়ার্ড কীভাবে কাজ করে
আপনি যখন synchronizedএকটি স্ট্যাটিক পদ্ধতিতে কীওয়ার্ডটি যুক্ত করেন , তখন পদ্ধতিটি কেবল একবারে একটি থ্রেড দ্বারা কল করা যেতে পারে।
আপনার ক্ষেত্রে, প্রতিটি পদ্ধতির কল এই করবে:
- নতুন একটি তৈরি কর
SessionFactory
- নতুন একটি তৈরি কর
Session
- সত্তা আনুন
- সত্তাকে কলারে ফিরিয়ে দিন
তবে এগুলি আপনার প্রয়োজনীয়তা ছিল:
- একই ডিবি উদাহরণটিতে তথ্য অ্যাক্সেস রোধ করতে আমি এটি চাই।
getObjectByIdযখন কোনও নির্দিষ্ট শ্রেণীর দ্বারা ডাকা হয় তখন সমস্ত ক্লাসের জন্য ডেকে আটকানো
সুতরাং, getObjectByIdপদ্ধতিটি থ্রেড-নিরাপদ হলেও বাস্তবায়নটি ভুল।
SessionFactory সেরা অনুশীলন
SessionFactoryথ্রেড-নিরাপদ, এবং এটা যেমন সত্তা শ্রেণীর পার্স এবং অভ্যন্তরীণ সত্তা metamodel উপস্থাপনা গড়ে তুলতে প্রয়োজন তৈরি করতে একটি খুব ব্যয়বহুল বস্তু আছে।
সুতরাং, আপনার SessionFactoryপ্রতিটি getObjectByIdপদ্ধতি কল চালু করা উচিত নয় ।
পরিবর্তে, আপনার এটির জন্য একটি সিঙ্গলটন উদাহরণ তৈরি করা উচিত।
private static final SessionFactory sessionFactory = new Configuration()
.configure()
.buildSessionFactory();
Sessionসবসময় বন্ধ করে দেওয়া উচিত
আপনি Sessionকোনও finallyব্লকটি বন্ধ করেননি এবং সত্তা লোড করার সময় যদি কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয় তবে এটি ডাটাবেস সংস্থানগুলি ফাঁস করতে পারে।
Session.loadপদ্ধতি অনুসারে জাভাডক একটি নিক্ষেপ HibernateExceptionকরতে পারে যদি সত্তাটি ডাটাবেসে পাওয়া যায় না।
কোনও উদাহরণ উপস্থিত রয়েছে কিনা তা স্থির করার জন্য আপনার এই পদ্ধতিটি ব্যবহার করা উচিত নয় ( get()পরিবর্তে ব্যবহার করুন)। এটি কেবলমাত্র অনুমান করে যে আপনার অস্তিত্ব রয়েছে তা পুনরুদ্ধার করতে এটি ব্যবহার করুন, যেখানে অস্তিত্বই একটি আসল ত্রুটি হবে।
এজন্য আপনাকে এটিকে finallyবন্ধ করার জন্য একটি ব্লক ব্যবহার করতে হবে Session:
public static synchronized Object getObjectById (Class objclass, Long id) {
Session session = null;
try {
session = sessionFactory.openSession();
return session.load(objclass, id);
} finally {
if(session != null) {
session.close();
}
}
}
বহু-থ্রেড অ্যাক্সেস প্রতিরোধ করা
আপনার ক্ষেত্রে, আপনি নিশ্চিত করতে চেয়েছিলেন যে কেবল একটি থ্রেড সেই নির্দিষ্ট সত্তায় অ্যাক্সেস পেয়েছে।
তবে synchronizedকীওয়ার্ডটি কেবল দুটি থ্রেডকে getObjectByIdএকই সাথে কল করতে বাধা দেয় । দুটি থ্রেড যদি একের পর এক এই পদ্ধতিটিকে কল করে তবে আপনার এই সত্তাটি ব্যবহার করে এখনও দুটি থ্রেড থাকবে।
সুতরাং, আপনি যদি কোনও প্রদত্ত ডাটাবেস অবজেক্টটি লক করতে চান যাতে অন্য কোনও থ্রেড এটি পরিবর্তন করতে না পারে, তবে আপনাকে ডাটাবেস লকগুলি ব্যবহার করতে হবে।
synchronizedমূলশব্দটি কেবল একটি একক জেভিএম-এ কাজ করে। আপনার যদি একাধিক ওয়েব নোড থাকে তবে এটি একাধিক জেভিএম জুড়ে মাল্টি-থ্রেড অ্যাক্সেসকে আটকাবে না।
আপনি কি করতে প্রয়োজন ব্যবহার LockModeType.PESSIMISTIC_READবাLockModeType.PESSIMISTIC_WRITE যখন ডিবি পরিবর্তন, ভালো প্রয়োগের:
Session session = null;
EntityTransaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.getTransaction();
tx.begin();
Post post = session.find(
Post.class,
id,
LockModeType.LockModeType.PESSIMISTIC_READ
);
post.setTitle("High-Performance Java Perisstence");
tx.commit();
} catch(Exception e) {
LOGGER.error("Post entity could not be changed", e);
if(tx != null) {
tx.rollback();
}
} finally {
if(session != null) {
session.close();
}
}
সুতরাং, আমি এটিই করেছি:
- আমি একটি নতুন তৈরি করেছি
EntityTransactionএবং একটি নতুন ডাটাবেস লেনদেন শুরু করেছি
Postসম্পর্কিত ডাটাবেস রেকর্ডটিতে একটি লক ধরে রাখার সময় আমি সত্তাটি লোড করেছি
- আমি
Postসত্তাটি পরিবর্তন করেছি এবং লেনদেনের প্রতিশ্রুতিবদ্ধ
Exceptionনিক্ষিপ্ত হওয়ার ক্ষেত্রে , আমি লেনদেনটি ফিরিয়ে আনি
এসিডি এবং ডাটাবেস লেনদেন সম্পর্কে আরও তথ্যের জন্য, এই নিবন্ধটিও পরীক্ষা করে দেখুন ।