JdbcTemplate es la clase central en el paquete principal JDBC. Maneja la creación y liberación de recursos, lo que ayuda a evitar errores comunes como olvidar cerrar una conexión. Realiza las tareas básicas del flujo de trabajo principal de JDBC (como crear y ejecutar declaraciones), dejando que el código de la aplicación proporcione SQL y recupere los resultados. Clase JdbcTemplate:

  • Ejecuta consultas SQL

  • Actualiza declaraciones y llamadas a procedimientos almacenados

  • Itera a través de instancias de ResultSet y extrae los valores de los parámetros de retorno.

  • Captura excepciones JDBC y las convierte en un typed , una jerarquía de excepciones más descriptiva definida en el paquete org.springframework.dao. (Consulte Jerarquía coherente de excepciones).

Si usa la plantilla JdbcTemplate para su código, solo necesita implementar las interfaces de devolución de llamada proporcionándoles un contrato bien definido. Dada una Connection proporcionada por una clase JdbcTemplate, la interfaz de devolución de llamada PreparedStatementCreator crea una declaración compilada, proporcionando el SQL y todos los parámetros necesarios. Lo mismo ocurre con la interfaz CallableStatementCreator, que crea declaraciones invocables. La interfaz RowCallbackHandler recupera los valores de cada fila del ResultSet.

Puedes usar JdbcTemplate dentro de un Implementación de DAO al crear una instancia directa con una referencia a DataSource, o puede configurarlo en el contenedor Spring IoC y pasarlo al DAO como una referencia de bean.

DataSource siempre debe configurarse como un bean en el contenedor Spring IoC. En el primer caso, el frijol pasa directamente al servicio; en el segundo caso, se pasa a la plantilla preparada.

Todo el SQL producido por esta clase se registra en el nivel DEBUG en la categoría correspondiente al nombre de clase completo de la instancia de plantilla (normalmente JdbcTemplate, pero puede ser diferente si está utilizando una subclase personalizada de JdbcTemplate)

Las siguientes secciones proporcionan algunos ejemplos de usando JdbcTemplate. Estos ejemplos no son una lista exhaustiva de todas las funciones proporcionadas por JdbcTemplate. Ver el complemento javadoc .

Construcción de consultas (SELECT)

La siguiente consulta le permite obtener el número de filas en una relación:

Java
int rowCount =
        this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class);
Kotlin
val rowCount = jdbcTemplate.queryForObject<Int>("select count(*) from t_actor")!!

La siguiente consulta utiliza una variable de enlace:

Java
int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject( "select count(*) de t_actor donde first_name = ?", Integer.class, "Joe");
Kotlin
val countOfActorsNamedJoe = jdbcTemplate.queryForObject<Int>( "seleccione count(*) de t_actor donde first_name =?, arrayOf("Joe"))!!

La siguiente consulta busca String:

Java
String lastName = this.jdbcTemplate.queryForObject( "select last_name from t_actor donde id = ?" , String.class, 1212L);
Kotlin
val lastName = this.jdbcTemplate .queryForObject<String> ( "¡¡seleccione apellido de t_actor donde id =?, arrayOf(1212L))!!

La siguiente consulta busca y completa un dominio objeto:

Java
Actor actor = jdbcTemplate.queryForObject( "seleccione nombre, apellido de t_actor donde id =?", (resultSet, rowNum) -> { Actor nuevoActor = nuevo Actor(); newActor.setFirstName(resultSet.getString("primer_nombre")); newActor.setLastName(resultSet.getString("apellido")); devolver nuevoActor; }, 1212L);
Kotlin
val actor = jdbcTemplate.queryForObject( "seleccione nombre, apellido de t_actor donde id =?", arrayOf(1212L)) { rs, _ -> Actor(rs.getString("first_name"), rs.getString("last_name")) }

La siguiente consulta busca y completa una lista de dominios objetos:

Java
Lista<Actor> actores = this.jdbcTemplate.query( "seleccione nombre, apellido de t_actor", (resultSet, rowNum) -> { Actor actor = new Actor(); actor.setFirstName(resultSet.getString("first_name")); actor. setLastName(resultSet.getString("last_name")); return actor; });
Kotlin
val actores = jdbcTemplate.query("seleccione nombre, apellido de t_actor") { rs, _ -> Actor(rs.getString("first_name"), rs.getString("last_name"))

Si los dos últimos fragmentos de código realmente existieron en el mismo application , entonces tendría sentido eliminar la duplicación presente en las dos expresiones lambda RowMapper y extraerlas en un solo campo, al que luego se podría hacer referencia mediante métodos DAO según sea necesario. Por ejemplo, es mejor escribir el fragmento de código anterior de la siguiente manera:

Java
RowMapper final privado<Actor> actorRowMapper = (conjunto de resultados, número de fila) -> { Actor actor = nuevo Actor(); actor.setFirstName(resultSet.getString("primer_nombre")); actor.setLastName(resultSet.getString("apellido")); actor de regreso; }; Lista pública<Actor> findAllActors() { return this.jdbcTemplate.query("seleccione nombre, apellido de t_actor", actorRowMapper); }
Kotlin
val actorMapper = RowMapper<Actor> { rs: Conjunto de resultados, número de fila: Int -> Actor(rs.getString("first_name"), rs.getString("last_name")) } fun findAllActors(): Lista<Actor> { return jdbcTemplate.query("seleccione nombre, apellido de t_actor", actorMapper) }

Actualizar (INSERT, ACTUALIZAR y DELETE) usando JdbcTemplate

Puedes usar el método update(..) para realizar operaciones de inserción, actualización y eliminación. Los valores de los parámetros generalmente se proporcionan como argumentos variables o, alternativamente, como una matriz de objetos.

El siguiente ejemplo muestra cómo insertar una nueva entrada:

Java
this.jdbcTemplate.update( "insertar en t_actor (nombre, apellido) valores (?, ?)", "Leonor", "Watling");
Kotlin
jdbcTemplate.update( "insertar
        en t_actor (first_name, last_name) valores (?, ?)", "Leonor", "Watling")

El siguiente ejemplo muestra la actualización de un registro existente:

Java
this.jdbcTemplate.update( "actualizar t_actor set last_name =? donde id = ?", "Banjo", 5276L);
Kotlin
jdbcTemplate.update( "actualizar t_actor set last_name = ? donde id = ?, "Banjo", 5276L)

El siguiente ejemplo muestra cómo eliminar una entrada:

Java
this.jdbcTemplate.update( "eliminar de t_actor donde id =?, Long.valueOf(actorId));
Kotlin
jdbcTemplate.update("eliminar de t_actor donde id =?, actorId.toLong())

Otras operaciones JdbcTemplate

Puede utilizar el método execute(..) para ejecutar SQL arbitrario. En consecuencia, este método se utiliza a menudo para declaraciones en lenguaje de definición de datos (DDL). Está muy cargado de opciones que aceptan interfaces de devolución de llamada, vinculan matrices de variables, etc. El siguiente ejemplo crea una tabla:

Java
this.jdbcTemplate.execute("crear tabla mytable (id entero, nombre varchar(100))");
Kotlin
jdbcTemplate.execute("crear tabla mytable (id entero, nombre varchar(100))") 

El siguiente ejemplo llama a un procedimiento almacenado:

Java
this.jdbcTemplate. update( "llamar a SUPPORT.REFRESH_ACTORS_SUMMARY(?)", Long.valueOf(unionId));
Kotlin
jdbcTemplate .update( "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)", unionId.toLong())

Soporte mejorado para procedimientos almacenados se describe con más detalle.

Prácticas recomendadas para trabajar con JdbcTemplate

Una vez completada la configuración, las instancias de la clase JdbcTemplate son seguras para subprocesos. Esto es importante porque significa que puede configurar una instancia JdbcTemplate y luego inyectar de forma segura esa referencia compartida en múltiples DAO (o repositorios). JdbcTemplate tiene estado porque almacena una referencia a DataSource, pero este estado no es un estado de diálogo.

Prácticas recomendadas al utilizar JdbcTemplate (y la clase asociada NamedParameterJdbcTemplate ) es la configuración de DataSource en el archivo de configuración de Spring, y luego inyectar la dependencia de ese bean DataSource común en las clases DAO. JdbcTemplate se crea en el configurador de DataSource. Esto da como resultado un DAO que se parece a esto:

Java
clase pública JdbcCorporateEventDao implementa CorporateEventDao { private JdbcTemplate jdbcTemplate; setDataSource público vacío (Fuente de datos fuente de datos) { this.jdbcTemplate = nuevo JdbcTemplate (fuente de datos); } // Las implementaciones de los métodos CorporateEventDao con soporte JDBC siguen... }
Kotlin
clase JdbcCorporateEventDao(dataSource : DataSource) : CorporateEventDao { private val jdbcTemplate = JdbcTemplate(dataSource) // Las implementaciones habilitadas para JDBC de los métodos CorporateEventDao siguen... }

El siguiente ejemplo muestra la configuración XML correspondiente:

 <?xml versión="1.0" codificación="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http:// www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http:/ /www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <bean id="corporateEventDao" class="com.example.JdbcCorporateEventDao"> <nombre de propiedad="fuente de datos" ref="fuente de datos"/> </frijol> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <nombre de propiedad="url" valor="${jdbc.url}"/> <property name="nombre de usuario" value="${jdbc.username}"/> <nombre de propiedad="contraseña" valor="${jdbc.contraseña}"/> </frijol> <context:property-placeholder ubicación="jdbc.properties"/> </beans>

Una alternativa a la configuración explícita es utilizar el escaneo de beans y admitir anotaciones para la inyección de dependencias. En este caso, puede marcar la clase con la anotación @Repository (lo que la convierte en candidata para el escaneo de componentes) y marcar el definidor DataSource con @Autowired anotación. El siguiente ejemplo muestra cómo hacer esto:

Java
@Repository  clase pública JdbcCorporateEventDao implementa CorporateEventDao { JdbcTemplate privado jdbcTemplate; @Autowired public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource);  } // Las implementaciones habilitadas para JDBC de los métodos CorporateEventDao siguen... }
  1. Anotar la clase con @Repository.
  2. Anotar el definidor DataSource con @Autowired.
  3. Cree un nuevo JdbcTemplate usando DataSource.
Kotlin
@Repository  class JdbcCorporateEventDao(dataSource: DataSource): CorporateEventDao {  private val jdbcTemplate = JdbcTemplate(dataSource)  // Implementaciones de métodos CorporateEventDao con soporte JDBC sigue... }
  1. Anota la clase con @Repository.
  2. Inyección del constructor de DataSource.
  3. Crea un nuevo JdbcTemplate usando DataSource .

El siguiente ejemplo muestra la configuración XML correspondiente:

<?xml version="1.0"
        encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://
        www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http:/ /www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd"> <!-- Busque en el paquete de la
        aplicación base clases con la anotación @Component para configurarlas como beans --> <context:component-scan
        base-package="org.springframework.docs.test" /> <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName"
        value="${jdbc.driverClassName}"/> <nombre de propiedad="url" valor="${jdbc.url}"/> <property
        name="nombre de usuario" value="${jdbc.username}"/> <nombre de propiedad="contraseña"
        valor="${jdbc.contraseña}"/> </frijol> <context:property-placeholder ubicación="jdbc.properties"/>
        </beans>

Si está utilizando la clase JdbcDaoSupport de Spring y tiene varias clases DAO habilitadas para JDBC adjuntas entonces su subclase hereda el método setDataSource(..) de la clase JdbcDaoSupport. Puede determinar si heredar de esta clase. La clase JdbcDaoSupport se proporciona únicamente por conveniencia.

Independientemente de cuál de los estilos de inicialización de plantilla descritos anteriormente decida usar (o no usar), rara vez es necesario cree una nueva instancia de JdbcTemplate siempre que necesite ejecutar SQL. Una vez completada la configuración, la instancia JdbcTemplate es segura para subprocesos. Si su aplicación accede a varias bases de datos, es posible que necesite varias instancias JdbcTemplate, lo que requiere varias fuentes de datos y, en consecuencia, varias instancias configuradas de forma diferente de JdbcTemplate.