O PreparedStatement resolve mesmo!!
o chato do PreparedStatement é que vc tem que passar um java.sql.Date pra ele e não um java.util.Date. Mas vale o preço…
Quando vc faz queries diretamente com Strings, vc pode fazer assim:
java.util.Date myDate = ...
java.sql.Date sqld = new java.sql.Date(myDate);
StringBuffer buf = new StringBuffer("UPDATE clientes SET nome = ");
...
buf.append(" nascimento = '");
buf.append(sqld.toString()); // explícito, mas podia ser buf.append(sqld);
buf.append("' WHERE");
...
No seu código, faltou isso: o apóstrofo em volta da data. Vc tb pode usar o formato “yyyy-MM-dd”, que é o formado do java.sql.Date.
No caso especial do Oracle, eu já vi um fenômeno estranho com PreparedStatements e java.sql.TimeStamps: a gente tinha que zerar os nanossegundos de todos os timestamps antes de gravar no banco, senão não dava pra testar a igualdade de jeito nenhum:
stamp.setNanos(0);
Isso é estranho pq o Oracle afirma ignorar os nanossegundos, pelo menos no help online.