10 Haziran 2015 Çarşamba

JDBC/ADO.Net

Never do in code what you can get the SQL Server to do well for you
Bu prensip asla kodun içinde join, veri filtreleme (where), foreign key integrity, primary key integrity, aggregate işlemlerinin yapılmaması gerektiğini belirtir.

JDBC sınıf hiyerarşisi kabaca aşağıdaki gibi
DriverManager
Konuyu DriverManager sıfını yazısına taşıdım.

JDBC ve ? işareti
JDBC ile ilgili öğrenilmesi gereken ilk konu JDBC kütüphanesi verdiğimiz SQL cümleleri ile "?" işareti gibi özel karakterler hariç bilmezler.SQL cümlelerine parametre geçilebilir ancak bazı DDL cümleleri parametre kabul etmezler. Bu tür cümleleri stringleri birleştirerek oluşturmak gerekir. Örneğin "DROP Table ?" şeklindeki bir DDL çalışmayabilir.

JDBC ve kapatılması gereken nesneler
close
JDBC kullanırken ResultSet, Statement ve Connection nesnelerinin işimiz bittikten sonra kapatılmaları gerekir. Örnek:

Connection Arayüzü
setSavepoint
Bu metod ile eğer veritabanı destekliyorsa açılmış olan transaction tamamen geri alınmadan belli bir noktaya kadar geri sarılabilir. Örnek:
stmt = conn.createStatement();
sp = conn.setSavepoint();
stmt.executeUpdate("INSERT INTO test(id) VALUES(1)");
conn.rollback(sp);
setTransactionIsolation
Bu metod ile isolation seviyesi atanır. Örnek:
getConnection().setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Statement Arayüzü
Difference between Statement and PreparedStatement sorusuna verilen cevapta görüldüğü gibi PreparedStatement sınıfı Statement sınıfına tercih edilmeli. Yine de bazı örnekler vermekte fayda var.

cancel
Bu metod ile çalışmakta olan bir Statement iptal edilebilir.

execute
boolean execute(string) metodunu sql cümlelerinin ne yaptığını bilmeden (insert/update/delete gibi) çağırmak için kullanırız. Örneği buradan aldım.
Bu metod sadece Select cümlesi için çağırıldığında true döner. Diğer kullanımlarda hep false döner.
executeUpdate
Bu metod kaç tane satırın güncellendiğini döndürür, ResultSet döndürmez ! Örnek:

Statement stmt = con.createStatement();
int rows = stmt.executeUpdate( insertStr );
System.out.printf("%d row(s) updated!", rows);
Zaten javadoc açıklamasında da dönüş değerini görmek mümkün.


executeQuery (Select cümleleri için kullanılır)
Bu metod ile bir ResultSet döndürülür. Örnek:

PreparedStatement pst = con.prepareStatement("select * from users where username=? ");
pst.setString(1,userName);
ResultSet rs=pst.executeQuery();
if(rs.next()) {
    String userClass=rs.getString("Class");
}
getGeneratedKeys
Bu metod ile bazı veritabları tarafından otomatik olarak üretilen anahtar değerler alınıyor. Örnek:
ResultSet rs = stmt.getGeneratedKeys();
while(rs.next()) {
    String key = rs.getString(1);//Anahtar String olarak geliyor
}
PreparedStatement Arayüzü Setter Metodları
setCharacterStream - Clob yazmak için kullanılır
Bu metod için örneği buradan aldım.
PreparedStatement pstmt = conn.prepareStatement("insert into clob_table (id, clob_colum) values (?,?)");
String clobData = "....";
Reader reader = new StringReader(clobData);
pstmt.setInt(1, 42);
pstmt.setCharacterStream(2, reader, clobData.length());
pstmt.executeUpdate();
setBinaryStream - Blob yazmak için kullanılır
Bu metod için örneği buradan aldım.
File f = new File(path);
FileInputStream fis = new FileInputStream(f);
PreparedStatement preparedStmt = con.prepareStatement(insertstatement);
preparedStmt.setBinaryStream(1, fis, f.length());
setDate - java.sql.Date yazmak için kullanılır
Bu metod ile java.sql.Date sınıfı yazılır. Bu sınıfı yaratmak için aşağıdaki gibi yapmak gerekir.

java.util.Date utilDate = //doldur;
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());

setNull metodu
Bu metod ile Spring StoredProcedure Optional Parameters sorusunda açıklandığı gibi null parametre gönderebilme imkanımız var. Örnek :
setNull (1,null); veya setNull (1,Types.NULL) şeklinde olabilir.
Types sınıfı java.sql paketinde geçiyor.

setObject metodu
PreparedStatement arayüzü ile setObject, setString, setTime gibi bir çok setter metod gelmekte. How to I prepare an argument of type: List<Entry<? extends Class<?>, ?>> sorusuna verilen cevaba göre setObject metodu kendisine verilen parametrenini tipine bakarak doğru metodu çağırabilme yeteneğine sahip. Örneğin aşağıda PostgreSQL veritabanının JDBC sürücüsünün kodu var, ve cevaba uygun görünüyor.


CallableStatement Arayüzü
Konuyu JDBC CallableStatement başlıklı yazıya taşıdım.

ResultSet Arayüzü
Konuyu JDBC ResultSet başlıklı yazıya taşıdım.

DatabaseMetaData
Bu arayüz bir Connection sınıfından elde ediliyor. Veritabanı hakkında bilgi toplamak için faydalı.
getTables
Bu metod ile veritabanındaki tablolar hakkında bilgi elde edilebiliyor. Örnek:
Connection con = DriverManager.getConnection( "jdbc:postgresql://localhost:5432/db","user","pass");
DatabaseMetaData md = con.getMetaData();
ResultSet rs = md.getTables(null, "public", "%", null);
while (rs.next()) {
    rs.getString(3);//TABLE_NAME
}
ResultSetMetaData
Bu arayüz bir ResultSet sınıfından elde ediliyor. Dikkat edilmesi gereken nokta ilk sütun 1'den başlar. Örnek :
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM TABLE2");
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
boolean b = rsmd.isSearchable(1); 
hane sayısı
getScale() ve getPrecision() metodları ile Oracle 'da Number olarak tanımlanmış bir sütunun hane sayısı bilgisini öğrenmek mümkün.

Clob
Clob kullanımı Using Large Objects sayfasında bulunabilir. Hiyerarşi ise aşağıdaki gibi


Datasource
DataSource aynı DriverManager gibi çalışıyor. Aralarındaki en önemli fark DataSource uygulama sunucusu tarafından JNDI vasıtasıyla verilir. Bir diğer fark ise DataSource, Connection Pooling imkanı sağlarken, DriverManager sunmaz.

Connection nesnesini JNDI vasıtasıyla almak için aşağıdakine benzer bir yöntem izlemek lazım.



Tomcat ile tüm uygulamalar için global bir connection pool yaratmak istiyorsak ayarları $CATALINA_BASE/conf/server.xml dosyasına , yok sadece bir web uygulamasına ait bir connection pool yaratmak istiyorsak uygulamanın META-INF/context.xml dosyasına eklemek lazım.

Hibernate

Hibernate ile hem DriverManager hem de JNDI kullanarak veritabanına bağlanmak mümkün. Bu konuyla ilgili olarak Spring ve Transaction/DAO başlıklı yazıya göz atabilirsiniz

JDBC Batch
Batch işlemler için java.sql.Statement arayüzündeki addBatch() ve   executeBatch() metodları kullanılır. Aşağıda PostgreSQL veritabanında batch işlemlerin nasıl bir ArrayList içine doldurulduğunu görmek mümkün.

Not : Batch Insertion in Hibernate ve Hibernate ile DAO ve Castle.ActiveRecord kullanımı başlıklı yazılarda
Hibernate ile JDBC batch ayarları arasındaki ilişkiyi de görmek mmükün.

İlginç bir konu ise batch update yaparken güncellenen satırlara kilit konulması. Eğer konulan kilit sayısı belli bir sayıyı aşıyorsa, tüm tabloya kilit konulduğu yazılmış. Bu durumda bir başkası aynı tablodaki ilgisiz bir satırı güncelleyemez. Dolayısıyla batch güncelleme için 5000 sınırının geçilmemesi tavsiye edilmiş.

JDBC Gün Saat Sınıfları
JDBC Gün Saat Sınıfları yazısına taşıdım.

JDBC Ayarları

setFetchSize : Bu metod Statement arayüzüne ait. Veritabanından bir sorgu için kaç tane satırın getirileceğini gelirtir. Kimi veritabanı (örneğin Oracle default olarak sadece 10 satır gönderiyor). Bu konu ile ilgili bulduğum en faydalı link JDBC performance tuning with optimal fetch size başlıklı yazı
st.setFetchSize(int rows);
Aşağıdaki şekilde setFetchSize() metodunun PostgreSQL veritabanı ile nasıl çalıştığını gösteren bir şekil mevcut

setMaxRows
Tam ne işe yaradığını anlamadım ama şöyle kullanılıyor.
st.setMaxRows(int maxRows);

ADO.Net

ADO.Net ise aşağıdaki gibi


Ado.Net ile asenkron SQL sorguları çalıştırmak ta mümkün. Aşağıdaki şekilde bunu görmek mümkün.
SQLConnection sınıfı
SQLConnection yazısına taşıdım.

SqlCECommand sınıfı
Örnek:
SqlCeCommand com = new SqlCeCommand("INSERT INTO ... VALUES(@CategoryName)",con);

SqlCommand sınıfı
Bu sınıf JDBC'deki Statement sınıfına benziyor. Çalışmak için bir connection nesnesine ihtiyaç duyuyor. Connection nesnesi constructor içinde verilebilir veya property olarak atanabilir.

Property olarak atamak
using (connection)
{
  cmd.Connection = connection; //Here assign connection to command object
        
}//end using(connection)

ExecuteNonQuery metodu
Bu metod kaç tane satırın etkilendiğini döner. Bu açıdan JDBC'deki executeUpdate metoduna benzer.

using (SqlCommand command = new SqlCommand("GP_SOP_AdjustTax", con, sqlTrans))
{
  try
  {
    

    if (con == null || con.State == ConnectionState.Closed)
    {
      con.Open();
    }

     command.ExecuteNonQuery();
    
     sqlTrans.Commit();
    }
    catch (Exception ex)
    {
      sqlTrans.Rollback();
    }
    finally
    {
      con.Close();
     }
}

ExecuteScalar metodu
Örnek:

const string sql = @"SELECT 
                        COUNT(CUSTOMER_NO) 
                     FROM 
                        WEBSITE_CUSTOMERS 
                     WHERE 
                        UPPER(CUSTOMER_NO) = @CUSTOMER_NO;";

using (SqlConnection connection = new SqlConnection("ConnectionString"))
{
    using (SqlCommand cmdCheck = new SqlCommand(sql, connection))
    {
        cmdCheck.Parameters.AddWithValue("@CUSTOMER_NO", "1");
        connection.Open();
        int nExists = (int)cmdCheck.ExecuteScalar();
        return nExists > 0;
    }
}

Parameters
SQL cümlelerine parametre geçmek için kullanılır. AddWithValue() metodu çağırılarak @ABC şeklindeki alanlara değer atanır.

SqlDataReader sınıfı
SqlDataReader yazısına taşıdım.

DataTable sınıfı
DataTable yazısına taşıdım.

DataSet sınıfı
DataSet yazısına taşıdım.

QT
Qt ise aşağıdaki gibi
QSqlDatabase
İsmi olan bir connection ekle
//Yeni bir connection ekle
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "Definitions");
//....
//Connection'ı kapat
QSqlDatabase::removeDatabase("Definitions");

İsimsiz default connection ekle
Örnek:
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
db.setHostName("acidalia");
db.setDatabaseName("customdb");
db.setUserName("mojito");
db.setPassword("J0a1m8");
bool ok = db.open();

SQLite örnekleri
SQLite dosya tabanlı bir veritabanı olduğu için kullanması çok kolay. Driver olarak qsqlite4.dll kullanılıyor. Bu dll $QTDIR\plugins\sqldrivers dosyası altında bulunur. Programı kurarken programın kurulduğu yerin altındaki sqldrivers alt dizini altına kopyalamak gerekir. How to deliver sqlite driver to the end user? sorusunda da benzer bir cevap verilmiş.

QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE",CONNECTION_NAME);
QString nativeDbPath = "myfile.db";
database.setDatabaseName(nativeDbPath);
database.open();

QSqlQuery
Bu sınıf JDBC'deki Statement ve PreparedStatement arayüzlerinin karışımına benziyor.
next metodu ile sorgulama işlemi
 
exec metodu ile silme işlemi
QSqlQuery DeleteQuery;
DeleteQuery.prepare("DELETE FROM Contacts WHERE Id = :i;");
DeleteQuery.bindValue(":i",SelectedRecordId);
if(!DeleteQuery.exec())
{
//error
}
OCI (Oracle Call Interface)
C ile Oracle veritabanına erişmek için kullanılır. OCI transport olarak SQLNET kullanır.

ODBC
ODBC kütüphanaleri artık sanırım sadece C++ uygulamaları tarafından kullanılıyor. Oracle hariç çoğu veritabanı için sadece ODBC kütüphanesi yeterli. Oracle ODBC kullanmak için Oracle Client yazılımının da kurulu olması gerekir.

Hiç yorum yok:

Yorum Gönder