synchronized
Java anahtar kelimesi nasıl çalışır?
synchronized
Anahtar 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.
getObjectById
belirli bir sınıf tarafından çağrıldığında tüm sınıflar için çağrılmayı önleme
Bu nedenle, getObjectById
yöntem iş parçacığı için güvenli olsa bile uygulama yanlıştır.
SessionFactory
en iyi uygulamalar
İş SessionFactory
parç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, SessionFactory
her getObjectById
yö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 Session
zaman kapalı olmalı
Session
Bir finally
blokta kapatmadınız ve varlık yüklenirken bir istisna atılırsa veritabanı kaynaklarına sızabilir.
Yönteme göre Session.load
JavaDocHibernateException
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 synchronized
anahtar kelime yalnızca iki iş parçacığının getObjectById
aynı 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.
synchronized
Anahtar 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_READ
veyaLockModeType.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:
EntityTransaction
Yeni bir veritabanı oluşturdum ve yeni bir veritabanı işlemi başlattım
- Ben yüklenen
Post
ilişkili veritabanı kayıt üzerinde kilit tutarken varlık
- Varlığı değiştirdim
Post
ve işlemi taahhüt ettim
Exception
Atı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.