No se necesita mucho código para ejecutar una declaración SQL. Requiere DataSource
y
JdbcTemplate
, incluidos los métodos auxiliares que se proporcionan con JdbcTemplate
. El
siguiente ejemplo muestra lo que se debe incluir en una clase mínima pero completamente funcional que crea una nueva
tabla:
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class ExecuteAStatement {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public void doExecute() {
this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
}
}
import javax.sql.DataSource
import org.springframework.jdbc.core.JdbcTemplate
class ExecuteAStatement(dataSource: DataSource) {
private val jdbcTemplate = JdbcTemplate(dataSource)
fun doExecute() {
jdbcTemplate.execute("create table mytable (id integer, name varchar(100))")
}
}
Ejecución de consultas
Algunos métodos de consulta devuelven un valor único. Para obtener un contador o un valor específico de una sola
línea, use queryForObject(..)
. Este último convierte el Type
devuelto de JDBC a la clase
Java pasada como argumento. Si la conversión de tipo no es válida, se generará una excepción InvalidDataAccessApiUsageException
.
El siguiente ejemplo contiene dos métodos de consulta, uno para int
y el otro para String
:
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class RunAQuery {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public int getCount() {
return this.jdbcTemplate.queryForObject("select count(*) from mytable", Integer.class);
}
public String getName() {
return this.jdbcTemplate.queryForObject("select name from mytable", String.class);
}
}
import javax.sql.DataSource
import org.springframework.jdbc.core.JdbcTemplate
class RunAQuery(dataSource: DataSource) {
private val jdbcTemplate = JdbcTemplate(dataSource)
val count: Int
get() = jdbcTemplate.queryForObject("select count(*) from mytable")!!
val name: String?
get() = jdbcTemplate.queryForObject("select name from mytable")
}
Además de los métodos de consulta de resultado único, varios métodos devuelven una lista con una entrada para cada
fila que devuelve la consulta. El método más escrito es queryForList(..)
, que devuelve una
List
, donde cada elemento es un Map
que contiene una entrada para cada columna. usando el
nombre de la columna como clave. Si agrega un método al ejemplo anterior para obtener una lista de todas las
cadenas, podría verse así:
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public List<Map<String, Object>> getList() {
return this.jdbcTemplate.queryForList("select * from mytable");
}
private val jdbcTemplate = JdbcTemplate(dataSource)
fun getList(): List<Map<String, Any>> {
return jdbcTemplate.queryForList("select * from mytable")
}
La lista resultante se verá así:
[{nombre=Bob, id=1}, {nombre=Mary, id=2}]
Actualización de base de datos
El siguiente ejemplo actualiza una columna para una clave principal específica:
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class ExecuteAnUpdate {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public void setName(int id, String name) {
this.jdbcTemplate.update("update mytable set name = ? where id = ?, name, id);
}
}
import javax.sql.DataSource
import org.springframework.jdbc.core.JdbcTemplate
class ExecuteAnUpdate(dataSource: DataSource) {
private val jdbcTemplate = JdbcTemplate(dataSource)
fun setName(id: Int, name: String) {
jdbcTemplate.update("update mytable set name = ? where id = ?, name, id)
}
}
En el ejemplo anterior, la instrucción SQL contiene marcadores de posición para parámetros de cadena. Puede pasar valores de parámetros como argumentos de longitud variable (varargs) o, alternativamente, como una matriz de objetos. Por lo tanto, debe envolver explícitamente los tipos primitivos en clases contenedoras de tipos primitivos o utilizar el autoboxing.
Obtener claves generadas automáticamente
El método auxiliar update()
admite la recuperación de las claves principales generadas por la base de
datos. Este soporte es parte del estándar JDBC 3.0. Para obtener más información, consulte el Capítulo 13.6 de la
especificación. El método toma PreparedStatementCreator
como primer argumento y así es como se
especifica la declaración de inserción requerida. El otro argumento es KeyHolder
, que contiene la clave
generada cuando la actualización se realiza correctamente. No existe una forma estándar única de crear una PreparedStatement
correspondiente (lo que explica por qué la firma del método es como es). El siguiente ejemplo funciona en Oracle,
pero es posible que no funcione en otras plataformas:
final String INSERT_SQL = "insert into my_test (name) values(?)";
final String name = "Rob";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(INSERT_SQL, new String[] { "id" });
ps.setString(1, name);
return ps;
}, keyHolder);
// keyHolder.getKey() ahora contiene la clave generada
val INSERT_SQL = "insert into my_test (name) values(?)"
val name = "Rob"
val keyHolder = GeneratedKeyHolder()
jdbcTemplate.update({
it.prepareStatement(INSERT_SQL, arrayOf("id")).apply { setString(1, name) }
}, keyHolder)
// keyHolder.getKey() ahora contiene la clave generada