30 Nisan 2017 Pazar

PreparedStatement Sınıfı

Giriş
Şu satırı dahil ederiz.
import java.sql.PreparedStatement;
Bu sınıf using ile kullanılmalı. Şöyle yaparız.
try (Connection con = DriverManager.getConnection("...")) {
  String sql = "select * from ...";
  try (PreparedStatement stmt = con.prepareStatement(sql)) {
    stmt.setInt(1, ...);
    stmt.setString(2, ...);
    ...
  }
}
setX metodlarına geçilen indeks sayısı 1'den başlar. Bu aslında bütün Java,C++,C# mantığına ters. Nedenini bilmiyorum. Şöyle yaparız.
String query = "SELECT id FROM `client_table` WHERE username= ?";
stmt = connection.prepareStatement (query);
stmt.setString (1, username);
ResultSet rs = stmt.executeQuery ();
if(rs.next ()){
  return UUID.fromString (rs.getString(1));
}else{
  return null;//id not found
}
constructor
Bir connection nesnesinden türetilir. Verilen sql cümlesi içinde ? işaret ile parametrelerin atanacağı alanlar olur. Şöyle yaparız.
PreparedStatement ps=con.prepareStatement("INSERT INTO ... VALUES (?,?)");
addBatch ve executeBath metodları
Eğer hata olursa BatchUpdateException fırlatır. Açıklaması şöyle
The subclass of SQLException thrown when an error occurs during a batch update operation. In addition to the information provided by SQLException, a BatchUpdateException provides the update counts for all commands that were executed successfully during the batch update, that is, all commands that were executed before the error occurred. The order of elements in an array of update counts corresponds to the order in which commands were added to the batch.
Bu kısmı anlamadım ancak hata olursa driver çalışmaya devam edebilir deniyor. Açıklaması şöyle.
After a command in a batch update fails to execute properly and a BatchUpdateException is thrown, the driver may or may not continue to process the remaining commands in the batch.
Hatalı satırlar görülebilir. Açıklaması şöyle.
In the case where the driver continues processing commands, the array element for any command that failed is Statement.EXECUTE_FAILED.
Bu iki metod genelde beraber kullanılır. Döngü içinde cümleleri ekleriz. Döngü sonunda executeBatch ile işleri topluca çalıştırırız. Şöyle yaparız.
PreparedStatement ps=con.prepareStatement("INSERT INTO ...");

while(somecondition)
{
  ....
  ps.setString(1, date);
  ps.setFloat(2, open);
  .....
  preparedStatement.addBatch();
}
preparedStatement.executeBatch();
Eğer cümleleri 100'er 100'er çalıştırmak istersek şöyle yaparız.
int batchSize = 100;
for (int count = 0; count < 1000; count++) {
  pStatement.setString(1, ...);
  pStatement.setString(2, ...);
  pStatement.addBatch();

  if (count % batchSize == 0) {
    pStatement.executeBatch();
  }
}

pStatement.executeBatch() ;//for remaining batch statements
close metodu
Şöyle yaparız.
ps.close();
executeQuery metodu
PrepararedStatement aynı zamanda Statement sınıfından kalıttığı için executeQuery(sql) metodunu da çağırabilir. Ancak bence çağırmamalı çünkü esas kullanım amacı şöyle
ResultSet results = ps.executeQuery();
Şu değil.
ResultSet results = state.executeQuery(sql);
executeUpdate metodu
Insert, Update cümlelerini çalıştırır. Şöyle yaparız.
ps.executeUpdate();
setBinaryStream metodu
Şöyle yaparız.
byte[] data = ...;
ByteArrayInputStream stream = new ByteArrayInputStream(data);
ps.setBinaryStream(1, stream, stream.available());
setDate metodu - tarih 
java.sql.Date nesnesi alır. Yani sadece tarih bilgisidir. Saat bilgisi içermez. Şöyle yaparız.
ps.setDate("...", new java.sql.Date());
setDouble metodu
Double için şöyle yaparız.
ps.setDouble(4,...);
setFloat metodu
Şöyle yaparız.
ps.setFloat (1, ...);
setInt metodu
Şöyle yaparız.
ps.setInt(1, ...);
setNull metodu
Şöyle yaparız.
ps.setNull(1, java.sql.Types.VARCHAR);
setObject metodu
Şöyle tanımlı olduğu için setX metodunun yerine kullanılabilir.
public void setObject(int parameterIndex, Object parameterObj) 
throws SQLException {
  synchronized (checkClosed().getConnectionMutex()) {
    if (parameterObj == null) {
      setNull(parameterIndex, java.sql.Types.OTHER);
    } else {
      if (parameterObj instanceof Byte) {
        setInt(parameterIndex, ((Byte) parameterObj).intValue());
      } else if (parameterObj instanceof String) {
        setString(parameterIndex, (String) parameterObj);
      } else if (parameterObj instanceof BigDecimal) {
        setBigDecimal(parameterIndex, (BigDecimal) parameterObj);
      } else if (parameterObj instanceof Short) {
        setShort(parameterIndex, ((Short) parameterObj).shortValue());
      } else if (parameterObj instanceof Integer) {
        setInt(parameterIndex, ((Integer) parameterObj).intValue());
      } else if (parameterObj instanceof Long) {
        setLong(parameterIndex, ((Long) parameterObj).longValue());
      } else if (parameterObj instanceof Float) {
        setFloat(parameterIndex, ((Float) parameterObj).floatValue());
      } else if (parameterObj instanceof Double) {
        setDouble(parameterIndex, ((Double) parameterObj).doubleValue());
      } else if (parameterObj instanceof byte[]) {
        setBytes(parameterIndex, (byte[]) parameterObj);
      } else if (parameterObj instanceof java.sql.Date) {
        setDate(parameterIndex, (java.sql.Date) parameterObj);
      } else if (parameterObj instanceof Time) {
        setTime(parameterIndex, (Time) parameterObj);
      } else if (parameterObj instanceof Timestamp) {
        setTimestamp(parameterIndex, (Timestamp) parameterObj);
      } else if (parameterObj instanceof Boolean) {
        setBoolean(parameterIndex, ((Boolean) parameterObj).booleanValue());
      } else if (parameterObj instanceof InputStream) {
        setBinaryStream(parameterIndex, (InputStream) parameterObj, -1);
      } else if (parameterObj instanceof java.sql.Blob) {
        setBlob(parameterIndex, (java.sql.Blob) parameterObj);
      } else if (parameterObj instanceof java.sql.Clob) {
        setClob(parameterIndex, (java.sql.Clob) parameterObj);
      } else if (this.connection.getTreatUtilDateAsTimestamp() &&
                 parameterObj instanceof java.util.Date) {
        setTimestamp(parameterIndex, 
                     new Timestamp(((java.util.Date) parameterObj).getTime()));
      } else if (parameterObj instanceof BigInteger) {
        setString(parameterIndex, parameterObj.toString());
      } else {
        setSerializableObject(parameterIndex, parameterObj);
      }
    }
  }
}
Eğer SQL tipini de vermek istersek şöyle yaparız. Böylece Unicode string gönderebiliriz.
ps.setObject(2,Id,Types.NVARCHAR);

setQueryTimeout metodu
Şöyle yaparız.
ps.setQueryTimeout (seconds);
setString metodu
Şöyle yaparız.
ps.setString(1, ...);
setTimeStamp metodu
Şöyle yaparız.
ps.setTimeStamp(1, new Timestamp(System.currentTimeMillis()));