Welcome

JPA, Hibernate ve JDBC Kullanırken AutoCommit Özelliği ve TXler

Doğrudan JDBC Kullanırken

JDBC spesifikasyonuna göre veritabanı bağlantılarının default autocommit değeri true’dur. Bu nedenle doğrudan JDBC ile işlem yaptığınızda veri üzerinde değişiklik yapan operasyonların her birisi kendi başına ayrı bir transaction’da ele alınacaktır. Transactional çalışabilmek için öncelikle bağlantının automcommit özelliğini false yapmanız gerekmektedir. Eğer veritabanı bağlantısı yaratılırken autocommit değerinin false olmasını istiyorsanız bunu DataSource’un defaultAutoCommit property’si üzerinden yapabilirsiniz. Yada doğrudan veritabanı üzerinde autocommit’i false olarak set edebilirsiniz. Örneğin hsqldb’de “set autocommit false” komutunu çalıştırmanız yeterlidir. Eğer Spring kullanıyorsanız, DriverManagerDataSource bean’ının connectionProperties property’si ile defaultAutoCommit’i false a set edebilirsiniz. Test ortamları için yazılmış olan SingleConnectionDataSource bean’ını kullanıyorsanız ya connectionProperties ile yada doğrudan autoCommit propertysi üzerinden false yapabilirsiniz.

Doğrudan Hibernate Kullanırken

Hibernate tarafında autocommit davranışı hibernate.connection.autocommit property’si ile düzenlenmektedir. Default olarak Hibernate autocommit’i false olarak set etmektedir, ve bu property ile oynanmaması önerilmektedir. Detaylar için Hibernate’in sitesindeki bu yazıyı okuyabilirsiniz. Peki autocommit false olunca ne oluyor? Autocommit false olduğunda veri erişim işlemleri yine eskiden olduğu gibi problemsiz gerçekleşiyor. Ancak insert, update, delete gibi veri üzerinde değişikliklere neden olan işlemler için Hibernate Session üzerinde mutlaka transaction başlatılması gerekiyor. Yapılan işlemler sonrasında ise iş akışına göre transaction commit veya rollback edilmeli ki yapılan değişiklikler veritabanına yansısın. Transaction başlatılmadan yapılan insert,delete, update işlemleri ile ilgili hiçbir hata olmamaktadır, Hibernate bu işlemleri sessizce göz ardı etmektedir.

<hibernate-configuration>
    <session-factory>
        <property name="connection.autocommit">true</property>
        <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
        <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="connection.url">jdbc:hsqldb:hsql://localhost</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"></property>
        <mapping class="examples.Foo"/>
    </session-factory>
</hibernate-configuration>
Foo foo = new Foo();
Configuration configuration = new AnnotationConfiguration().configure();
SessionFactory factory = configuration.buildSessionFactory();
Session session = factory.openSession();
session.save(foo);
session.close();

Eğer Hibernate ile çalışırken autocommit davranışını doğrudan JDBC kullanımı gibi yapmak istiyorsanız yapmanız gereken yukarıdaki örnekte gördüğünüz connection.commit property değerini true olarak set etmekten ibarettir. Bu durumda Hibernate Session üzerinde hiç transaction oluşturmandan veri manipülasyonu gerçekleştirebilirsiniz.

Spring ile Hibernate Kullanırken

Eğer Spring üzerinden Hibernate’i kullanıyorsanız işler biraz farklılaşmaktadır. Muhtemelen Hibernate SessionFactory nesnesini Spring’in LocalSessionFactoryBean factory bean’ı ile oluşturuyorsunuzdur. Hibernate SessionFactory bu durumda “user supplied connection” kullandığını düşünerek JDBC bağlantısını kendisi oluşturmak yerine doğrudan Spring’in inject ettiği DataSource bean’ından beklemektedir. Bu durumda da Hibernate’in hibernate.cfg.xml dosyası içerisinde belirteceğiniz connection.autocommit değişkeninin bir etkisi olmamaktadır. Veritabanı bağlantısının autocommit özelliği DataSource bean’ı nasıl konfigüre edilmişse ona göre değişmektedir. DriverManagerDataSource bean’ı defaultAutoCommit değerine bir değişiklik yapmadığı için de bu değer true olarak kalmakta ve Hibernate üzerinden gerçekleşen veri manipülasyonlarıda ortada bir transaction olmasa bile veritabanına yansıtılmaktadır. Doğrudan Hibernate kullanırken ki default Hibernate davranışını sağlamak için Spring ile konfigüre ettiğiniz DataSource bean’ına veritabanı bağlantısı oluşturuken autocommit’i false yapmasını söylemeniz gerekmektedir.

Foo foo = new Foo();
hibernateTemplate.persist(foo);

JPA ile Hibernate Kullanırken

Hibernate’i JPA ile kullanırken durum biraz daha değişmektedir. JPA, veri üzerinde manipülasyon yapan işlemler için mutlaka bir transaction beklemektedir. Sizin DataSource bean’ı üzerinde veya hibernate.cfg.xml içerisinde autocommit davranışını true yapmanızın bir etkisi olmamaktadır. Her iki durumda da transaction olmadan yapılan bir veri manipülasyonu javax.persistence.TransactionRequiredException ile sonuçlanmaktadır.

Foo foo = new Foo();
jpaTemplate.persist(foo);
jpaTemplate.flush();
Eğer yukarıdaki işlemin başarılı biçimde sonuçlanmasını istiyorsanız bu işlemi mutlaka bir transaciton içerisinde çalıştırmanız gerekmektedir.
Kısacası autocommit özelliği, Hibernate’in doğrudan kullanımı veya SessionFactory’nin Spring tarafından yönetilmesi, JPA üzerinden Hibernate kullanılması durumlarının her birinde farklı biçimlerde ele alınmaktadır. Bu nedenle yazdığınız servislerin veri erişim mekanizmaları farklılaştığında davranışlarında da değişiklikler söz konusu oluyorsa saşırmayın.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.

This site uses Akismet to reduce spam. Learn how your comment data is processed.