[JAVA] Passez facilement des appels JDBC avec Commons DbUtils

Une bibliothèque appelée Apache Commons DbUtils facilite l'écriture du code d'accès à la base de données que d'appeler directement l'API JDBC. Commons DbUtils est une petite bibliothèque plutôt qu'un grand framework, il a donc l'avantage d'être facile à déployer.

Obtenez Jar

Vous pouvez également télécharger Jar depuis la page de téléchargement sur le Site officiel, mais si vous utilisez Maven, ce qui suit est sur le POM Ce n'est pas grave si vous écrivez comme (Il semble que 1.7, la dernière version pour la première fois en 3 ans, vient de sortir).

<dependency>
  <groupId>commons-dbutils</groupId>
  <artifactId>commons-dbutils</artifactId>
  <version>1.7</version>
</dependency>

Comment appeler

Je vais vous présenter la méthode de base pour appeler Commons DbUtils.

Tout d'abord, créez un QueryRunner

Tout d'abord, créez une instance d'une classe appelée QueryRunner. Tout simplement nouveau sans argument, ou si vous utilisez un DataSource (pour le regroupement de connexions, etc.), prenez-le simplement comme argument et nouveau.

QueryRunner queryRunner = new QueryRunner();

//Si vous disposez d'un DataSource par certains moyens, cliquez ici.
DataSource dataSource = ... 
QueryRunner queryRunner = new QueryRunner(dataSource);

Exécuter les instructions INSERT, UPDATE, DELETE

Ensuite, je présenterai un exemple simple et facile à comprendre des méthodes qui exécutent des instructions SQL. Il s'agit d'un remplacement de la partie qui utilisait PreparedStatement # executeUpdate () dans l'appel JDBC direct. Plus précisément, c'est tout.

//Un exemple de UPDATE une ligne d'une table appelée Person
int rows = queryRunner.update(connection, "UPDATE Person SET Name = ? WHERE Id = ?", "Taro", 1);

Cela obligera QueryRunner à créer en interne un PreparedStatement, à définir les paramètres, à appeler executeUpdate () et à effectuer une série d'opérations de fermeture.

La valeur de retour est la même que la valeur de retour de PreparedStatement # executeUpdate (), c'est-à-dire que le nombre de lignes modifiées est renvoyé.

Le premier argument de connexion peut être omis si DataSource est passé lors de la création de QueryRunner. S'il est omis, getConnection () est appelé en interne et utilisé pour cette DataSource. Et il sera fermé automatiquement.

Les paramètres d'instruction SQL sont reçus sous forme d'arguments de longueur variable, vous pouvez donc effectuer les opérations suivantes, par exemple.

List<Object> params = new ArrayList<>();
params.add(...);
params.add(...);

queryRunner.update("...", params.toArray()); //Vous pouvez le transmettre sous la forme d'un tableau.

Exécutez l'instruction SELECT

Ensuite, je présenterai l'exécution de l'instruction SELECT. Il s'agit d'un remplacement de la partie qui utilisait PreparedStatement # executeQuery () dans l'appel JDBC direct. Contrairement à avant, lorsque vous exécutez une instruction SQL, un ResultSet est renvoyé, vous devez donc convertir comment obtenir le résultat dans la forme (type) souhaitée à partir de ce ResultSet. À cette fin, Common DbUtils fournit une interface appelée ResultSetHandler.

À titre d'exemple simple, si vous souhaitez récupérer la valeur de chaîne (c'est-à-dire une seule chaîne) pour une colonne particulière, pour un enregistrement particulier, pour une table particulière:

//Implémentez ResultSetHandler. Dans cet exemple, il a été implémenté en tant que classe anonyme.
//ResultSetHandler a un paramètre de type et spécifiez le type que vous souhaitez renvoyer ici. Cette fois, String.
ResultSetHandler<String> personNameHandler = new ResultSetHandler<String>() {
    @Override
    public String handle(ResultSet rs) throws SQLException {
        if (rs.next()) {
            //Renvoyez simplement la valeur dans la première colonne (bien qu'il n'y en ait qu'une) sous forme de chaîne.
            return rs.getString(1); 
        }
        return null;
    }
};

//La classe d'implémentation de ResultSetHandler est ResultSetHandler<String>Depuis sa mise en œuvre en tant que
//Le type du nom de la valeur de retour est String.
String name = queryRunner.query(connection, "SELECT Name FROM Person WHERE Id = ?", personNameHandler, 1);

De cette façon, le processus de conversion "quand un ResultSet est obtenu, comment le convertir" est exprimé comme un ResultSetHandler, et la méthode appelée QueryRunner # query () est appelée en l'incluant dans l'argument. En faisant cela, QueryRunner appelle en interne PreparedStatement # executeQuery (), applique ResultSetHandler # handle () au ResultSet renvoyé et exécute une série de traitements qui retourne le résultat. Les arguments autres que ResultSetHandler sont les mêmes que QueryRunner # update () (la connexion est omise, les paramètres sont passés en tant qu'arguments de longueur variable).

Classe d'implémentation de ResultSetHandler préparée à l'avance

Cette fois, j'ai implémenté ResultSetHandler moi-même, mais la classe d'implémentation ResultSetHandler utilisée dans des situations typiques comme cet exemple est déjà fournie dans Commons DbUtils. Vous devrez lire le Javadoc officiel (http://commons.apache.org/proper/commons-dbutils/apidocs/index.html) pour plus de détails, mais en voici quelques-uns.

ScalarHandler peut être utilisé dans les situations où vous souhaitez récupérer une seule valeur, comme dans cet exemple.

//Dans l'exemple précédent, c'était en fait OK.
String name = queryRunner.query("...", new ScalarHandler<>(), ...);

MapHandler convertit le résultat de SELECTing une ligne en une carte. Le nom de la colonne est la clé de la carte.

Map<String, Object> map = queryRunner.query("SELECT * FROM Person WHERE Id = ?", new MapHandler(), 1);

//Vous pouvez obtenir une carte comme celle-ci.
// map.get("Id") -> 1
// map.get("Name") -> "Taro"

BeanHandler convertit le résultat de SELECTing une ligne en un Java Bean.

//En supposant qu'une telle classe est définie ...
public class Person {
    private int id;
    private String name;
    //Ci-dessous, getter/Définition de setter ...
}
//En faisant cela, les champs Java seront définis en fonction du résultat de SELECT.
Person person = queryRunner.query("SELECT * FROM Person WHERE Id = ?", new BeanHandler<>(Person.class), 1);

Par défaut dans BeanHandler, le nom de la colonne de base de données et le nom de la propriété Java (nom du champ) doivent correspondre. Vous pouvez également donner la correspondance entre les noms de colonne et les noms de propriété sous forme de mappage en procédant comme suit.

//En supposant qu'une telle classe est définie ...
public class Person2 {
    private int id;
    private String fullName; //Cela ne correspond pas au nom de la colonne DB.
    //Ci-dessous, getter/Définition de setter ...
//Préparez une mappe avec le nom de la colonne de base de données comme clé et le nom de la propriété Java comme valeur.
Map<String, String> columnToPeroperty = new HashMap<>();
columnToPeroperty.put("Id", "id");
columnToPeroperty.put("Name", "fullName");

//Un objet de type RowProcessor peut être spécifié dans l'argument constructeur de BeanHandler.
//De plus, l'argument constructeur de BasicRowProcessor, qui est la classe d'implémentation de RowProcessor,
//Vous pouvez spécifier un objet de type BeanProcessor.
//De plus, vous pouvez passer la carte en tant qu'argument constructeur de BeanProcessor.

//Si vous faites ce qui précède de bas en haut ...
BeanProcessor beanProcessor = new BeanProcessor(columnToPeroperty);
RowProcessor rowProcessor = new BasicRowProcessor(beanProcessor);
ResultSetHandler<Person2> beanHandler = new BeanHandler<>(Person2.class, rowProcessor);

C'est tout pour la classe d'implémentation ResultSetHandler que vous pourriez utiliser souvent. De plus, afin d'interpréter le résultat de la sélection de plusieurs lignes, il existe une classe qui renvoie une liste ou une carte du résultat d'une ligne en tant qu'élément.

Obtient la clé générée automatiquement lorsque l'instruction INSERT est exécutée

Selon la table, il y aura souvent des colonnes qui sont automatiquement numérotées lors de INSERT. Insert () est utile au lieu de QueryRunner # update () lorsque vous souhaitez obtenir les valeurs de ces colonnes en même temps que vous effectuez un INSERT.

L'utilisation est similaire à la requête () utilisée lors de SELECTing, et le ResultSetHandler est spécifié comme argument. Ensuite, QueryRunner appelle en interne PreparedStatement # executeUpdate (), puis appelle PreparedStatement # getGeneratedKeys () pour obtenir le ResultSet, lui applique ResultSetHandler et renvoie le résultat. Te donnera.

Voici un exemple simple.

//Il existe une colonne appelée Id dans la table Person, et il est supposé que les numéros de série seront attribués lors de l'INSERT.
//Ici, j'ai utilisé ScalarHandler.
Integer taroId = queryRunner.insert("INSERT INTO Person(name) VALUES(?)", new ScalarHandler<>(), "Taro") ;

Recommended Posts

Passez facilement des appels JDBC avec Commons DbUtils
(Java) BDD facile avec Spectrum?
Micro service facile avec Spark Framework!
Sortie CSV par Apache Commons CSV
Utiliser Spring JDBC avec Spring Boot
Scraping Web facile avec Jsoup
Introduction facile à la bibliothèque avec Maven!
Utiliser SpatiaLite avec Java / JDBC