synchronizedJava anahtar kelimesi nasıl çalışır?
synchronizedAnahtar kelimeyi statik bir yönteme eklediğinizde, yöntem aynı anda yalnızca tek bir iş parçacığı tarafından çağrılabilir.
Sizin durumunuzda, her yöntem çağrısı:
- yeni bir tane oluştur
SessionFactory
- yeni bir tane oluştur
Session
- varlığı getir
- varlığı arayana geri döndürme
Ancak, bunlar gereksinimlerinizdi:
- Bu bilgi aynı DB örneği için erişimi önlemek istiyorum.
getObjectByIdbelirli bir sınıf tarafından çağrıldığında tüm sınıflar için çağrılmayı önleme
Bu nedenle, getObjectByIdyöntem iş parçacığı için güvenli olsa bile uygulama yanlıştır.
SessionFactory en iyi uygulamalar
İş SessionFactoryparçacığı için güvenlidir ve varlık sınıflarını ayrıştırmak ve iç varlık metamodel temsilini oluşturmak gerektiğinden oluşturmak çok pahalı bir nesnedir.
Bu nedenle, SessionFactoryher getObjectByIdyöntem çağrısında on oluşturmamalısınız .
Bunun yerine, bunun için tek bir örnek oluşturmalısınız.
private static final SessionFactory sessionFactory = new Configuration()
.configure()
.buildSessionFactory();
Her Sessionzaman kapalı olmalı
SessionBir finallyblokta kapatmadınız ve varlık yüklenirken bir istisna atılırsa veritabanı kaynaklarına sızabilir.
Yönteme göre Session.loadJavaDocHibernateException varlık veritabanında bulunamazsa a atabilir .
Bir örneğin olup olmadığını belirlemek için bu yöntemi kullanmamalısınız ( get()bunun yerine kullanın). Bunu yalnızca, var olmamanın gerçek bir hata olacağı varsayıldığınız bir örneği almak için kullanın.
Bu nedenle finally, kapatmak için bir blok kullanmanız gerekir 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();
}
}
}
Çok iş parçacıklı erişimi önleme
Sizin durumunuzda, belirli bir varlığa yalnızca bir iş parçacığının erişmesini sağlamak istediniz.
Ancak synchronizedanahtar kelime yalnızca iki iş parçacığının getObjectByIdaynı anda çağrılmasını önler . İki iş parçacığı bu yöntemi birbiri ardına çağırırsa, yine de bu varlığı kullanan iki iş parçacığınız olur.
Bu nedenle, belirli bir veritabanı nesnesini başka bir iş parçacığının değiştiremeyeceği şekilde kilitlemek istiyorsanız, veritabanı kilitlerini kullanmanız gerekir.
synchronizedAnahtar kelime tek bir JVM çalışır. Birden çok web düğümünüz varsa, bu, birden çok JVM'de çok iş parçacıklı erişimi engellemez.
Yapmanız gereken şey, değişiklikleri DB'ye uygularken LockModeType.PESSIMISTIC_READveyaLockModeType.PESSIMISTIC_WRITE şu şekilde uygulamanızdır:
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();
}
}
Ben de öyle yaptım:
EntityTransactionYeni bir veritabanı oluşturdum ve yeni bir veritabanı işlemi başlattım
- Ben yüklenen
Postilişkili veritabanı kayıt üzerinde kilit tutarken varlık
- Varlığı değiştirdim
Postve işlemi taahhüt ettim
ExceptionAtılan bir durumda , işlemi geri aldım
ACID ve veritabanı işlemleri hakkında daha fazla bilgi için bu makaleye de göz atın.