Une introduction ` a JDBC
1 Base de donn´ ees
1.1 Tester MySql
Un serveur MySql est accessible ` a partir des postes de travail (machine dbs-perso.luminy.univmed.fr ) et vous pouvez demander la cr´ eation d’une base de donn´ ees personnelle
1. Vous pouvez utiliser le client MySql (commande mysql ), ` a partir de votre machine pour vous connecter sur le serveur de bases de donn´ ees.
$ mysql -u utilisateur-bd -h dbs-perso.luminy.univmed.fr -p password: mot-de-passe re¸cu par mail
mysql> use nom-de-la-base;
mysql> cr´eation d’une table
Vous pouvez maintenant cr´ eer une ou plusieurs tables simples, en ajoutant des donn´ ees et en programmant quelques requˆ etes.
1.2 Utiliser HyperSQL
Si vous avez des difficult´ es avec la base personnelle MySQL, vous pouvez utiliser la base de donn´ ees embarqu´ ee HyperSQL
2. N’oubliez pas de lire la documentation HyperSQL
3.
1.3 Pilotes JDBC.
•
Cr´ eez dans Eclipse JEE un projet Java standard.
•
Ajoutez Maven ` a votre projet :
S´electionnez votre projet/
Bouton-droit/
Configure/
Convert to Maven Project. Vous devez `a cette ´ etape donner une num´ ero de version ` a votre projet. Laissez les valeurs par d´ efaut.
•
Cherchez sur MVNRepository
4le package mysql-connector-java
5et incluez dans le fichier pom.xml de votre projet les d´ ependances.
•
Profitez de cette ´ etape pour ajouter les d´ ependances de la base de donn´ ees embarqu´ ee HyperSQL
6.
2 Premiers programmes JDBC
•
Commencez par implanter puis tester l’exemple propos´ e
7.
•
´ Etudiez le
try-with-resourcesmise en oeuvre dans ces m´ ethodes (explications
8).
•
Ajoutez ` a la classe SimpleJdbc une m´ ethode de mise ` a jour ( updateName ) et testez-l` a.
•
V´ erifiez par un test unitaire que les injections SQL ne sont pas possibles pour cette m´ ethode.
1. ref:dosicalu 2. http://hsqldb.org/
3. ref:doc-hsqldb
4. http://mvnrepository.com 6. http://hsqldb.org/
7. simple-jdbc.html
8. http ://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
3 Spring et JDBC
Nous allons utiliser les outils de Spring pour simplifier l’utilisation de JDBC.
•
Ajoutez ` a votre fichier pom.xml les d´ ependances ci-dessous :
<!-- pour utiliser Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!-- pour utiliser la partie test de Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!-- pour utiliser la partie JDBC Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!-- pour les annotations (`a partir de java 10) -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
•
Dupliquez la classe SimpleJdbc en SimpleSpringJdbc .
•
Ajoutez ` a votre classe SimpleSpringJdbc une injection automatique d’une instance de JdbcTemplate (boite ` a outils JDBC de Spring) :
package simplejdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@Service
public class SimpleJdbcSpring {
@Autowired JdbcTemplate jt;
...
}
•
Cr´ eez maintenant une classe de configuration Spring pour pr´ eparer une instance de JdbcTemplate :
2
package simplejdbc;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
@Configurable
@ComponentScan(basePackages = "simplejdbc") public class SimpleJdbcConfig {
@Bean
// D´efinition des param`etres d’acc`es `a la BD public DataSource handMadeDataSource() {
var dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:hsqldb:file:testdb");
dataSource.setUsername("SA");
dataSource.setPassword("");
return dataSource;
}
@Bean
// Cr´eation d’une instance de JdbcTemplate
public JdbcTemplate myJdbcTemplate(@Autowired DataSource ds) { var t = new JdbcTemplate(ds);
return t;
} }
•
Vous pouvez maintenant pr´ eparer une nouvelle classe de test (aid´ ee par Spring) :
package simplejdbc;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = SimpleJdbcConfig.class) public class TestSimpleJdbcSpring {
@Autowired
SimpleJdbcSpring dao;
@Test
public void testSimleJdbcSample() { dao.initSchema();
dao.deleteName(100);
dao.deleteName(200);
dao.addName(100, "Hello");
dao.addName(200, "Salut");
assertEquals("Hello", dao.findName(100));
assertEquals("Salut", dao.findName(200));
for (String name : dao.findNames()) { System.out.printf("name=%s\n", name);
} }
@Test
public void testErrors() {
assertThrows(DuplicateKeyException.class, () -> { dao.initSchema();
dao.addName(100, "Hello");
dao.addName(100, "Salut");
});
} }
Travail `a faire
: avec l’aide de JdbcTemplate et des m´ ethodes propos´ ees (consultez la Javadoc
9), reprogrammez les m´ ethodes de la classe SimpleJdbcSpring . V´ erifiez ` a chaque fois que le test unitaire est positif.
4 Faire disparaˆıtre les constantes
Si nous souhaitons faire disparaitre les constantes dans la classe de configuration, nous devons
•
pr´ eparer un fichier de propri´ et´ es ( config.properties dans le r´ epertoire source) :
9. https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html
4
jdbc.url=jdbc:hsqldb:file:testdb jdbc.user=SA
jdbc.password=
•
utiliser ces propri´ et´ es dans la d´ efinition d’une DataSource :
package simplejdbc;
...
@Configurable
@ComponentScan(basePackages = "simplejdbc")
@PropertySource("classpath:config.properties") public class SimpleJdbcConfig {
...
@Bean
@Primary
// Cr´eer une dataSource `a partir des propri´et´es public DataSource paramDataSource(
@Value("${jdbc.url}") String url,
@Value("${jdbc.user}") String user,
@Value("${jdbc.password}") String password ) {
var dataSource = new DriverManagerDataSource();
dataSource.setUrl(url);
dataSource.setUsername(user);
dataSource.setPassword(password);
return dataSource;
} }
5 Utiliser un Javabean
Commencez par pr´ eparer le Javabean de repr´ esentation des noms :
package simplejdbc;
import java.io.Serializable;
public class Name implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
public int getId() { return id;
}
public String getName() { return name;
}
public void setId(int id) { this.id = id;
}
public void setName(String name) { this.name = name;
}
@Override
public String toString() {
return "Name [id=" + id + ", name=" + name + "]";
} }
Travail `a faire
: utilisez ce Javabean pour revoir les signatures des m´ ethodes de la classe SimpleJdbcSpring :
public List<Name> findNames() { ...
}
Vous aurez besoin d’utiliser un
mapperc’est-` a-dire une m´ ethode qui va construire une instance de la classe Name ` a partir d’une ligne de la base de donn´ ees repr´ esent´ ee par un ResultSet :
private static Name nameMapper(ResultSet rs, int i) throws SQLException { var n = new Name();
n.setId(rs.getInt("id"));
n.setName(rs.getString("name"));
return n;
}
6 Utiliser les DataSource
Nous allons maintenant passer par une DataSource pour obtenir un pool de connexions :
•
Ajoutez les d´ ependances pour Apache Commons DBCP
10.
10. http://commons.apache.org/dbcp/
6
<!-- pour les DataSource dbcp2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.6.0</version>
</dependency>
•
Pr´ eparez dans SimpleJdbcSpring un travail long :
public void longWork() {
try (var c = jt.getDataSource().getConnection()) { Thread.sleep(5000);
} catch (InterruptedException e) { } catch (SQLException e1) {
} }
•
Dans la classe SimpleJdbcConfig , ajoutez nune nouvelle usine pour ce DataSource :
@Bean
@Primary
// D´efinition des param`etres d’acc`es `a la BD public DataSource dbcp2DataSource() {
var dataSource = new BasicDataSource();
dataSource.setUrl("jdbc:hsqldb:file:testdb");
dataSource.setUsername("SA");
dataSource.setPassword("");
dataSource.setInitialSize(5); // ouvrir cinq connexions dataSource.setMaxTotal(5); // pas plus de cinq connexions return dataSource;
}
•
Pr´ eparez un test qui va cr´ eer une dizaine de threads pour tester l’allocation des connexions :
@Test
public void testWorks() throws Exception { long debut = System.currentTimeMillis();
// ex´ecution des threads
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 1; (i < 5); i++) { executor.execute(dao::longWork);
}
// attente de la fin des threads executor.shutdown();
executor.awaitTermination(10, TimeUnit.HOURS);
// calcul du temps de r´eponse
long fin = System.currentTimeMillis();
System.out.println("duree = " + (fin - debut) + "ms");
}
•