Ceci est un mémo d'étude pour obtenir la qualification Gold de Java8. Il semble qu'il n'y ait pas de mécanisme «try-with-resource» dans Scala, donc la seconde moitié décrit comment l'implémenter dans Scala.
Java
Créez une classe de gestion des connexions.
import java.sql.*;
/**
 *Classe d'acquisition de connexion DB
 */
public class DbConnector {
    public static Connection getConnect() throws SQLException {
        String url = "jdbc:mysql://localhost/golddb";
        String user = "username";
        String password = "password";
        Connection connection = DriverManager.getConnection(url, user, password);
        return connection;
    }
}
Connectez-vous en utilisant try-with-resource.
Les points de base sont les suivants.
Connection et obtenez une connexionStatement à l'aide de la connexion.Statement est utilisé, et le résultat est stocké dans l'objet ResultSet`.import java.sql.*;
public class JDBCExecuteQuerySample {
    public static void main(String[] args) {
        String sql = "SELECT dept_name FROM department";
        try (Connection connection = DbConnector.getConnect();
             Statement stmt = connection.createStatement()) {
            ResultSet rs = stmt.executeQuery(sql);
            if (rs != null) {
                System.out.println("rs != null");
            }
            while (rs.next()) {
                System.out.println("dept_name : " + rs.getString(1));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
import java.sql.*;
public class JDBCExecuteUpdateSample {
    public static void main(String[] args) {
        try (Connection connection = DbConnector.getConnect();
             Statement stmt = connection.createStatement()) {
            String sql =
                    "INSERT INTO department VALUES (6 , 'Plannning', 'Yokohama', '909-000-0000')";
            int col = stmt.executeUpdate(sql);
            System.out.println("col : " + col);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
}
import java.sql.*;
public class JDBCExecuteSample {
    public static void main(String[] args) {
        try (Connection connection = DbConnector.getConnect();
             Statement statement = connection.createStatement()) {
            String[] sqls = {
                    //"insert into department values " + "(7, 'Planning', 'Yokohama', '055-555-5555')",
                    "select dept_name from department where dept_code = 2"
            };
            for (String sql : sqls) {
                //La valeur de retour de la méthode execute est booléenne
                boolean isResultSet = statement.execute(sql);
                if (isResultSet) { //En cas de sélection, le résultat de isResultSet est vrai.
                    //Lorsqu'il est exécuté par execute, l'objet de ResultSet
                    // getResultSet()Obtenir par méthode
                    ResultSet rs = statement.getResultSet();
                    rs.next();
                    System.out.println(rs.getString(1));
                } else { //IsResultSet est faux pour l'insertion
                    int count = statement.getUpdateCount();
                    System.out.println(count);
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
PreparedStatement
Dans la plupart des cas, utilisez PreparedStatement au lieu de Statement pour empêcher l'injection SQL.
import java.sql.*;
public class JDBCPreparedStatementSample {
    public static void main(String[] args) {
        String sql = "SELECT dept_code, dept_name FROM department WHERE dept_name = ?";
        try (Connection connection = DbConnector.getConnect();
             PreparedStatement statement = connection.prepareStatement(sql)) {
            // ?Définissez la partie de et exécutez.
            statement.setString(1, "Education");
            ResultSet resultSet = statement.executeQuery();
            resultSet.next();
            System.out.format("dept_code: %d, dept_name: %s",
                    resultSet.getInt(1), resultSet.getString(2));
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
En plus d'utiliser l'objet ResultSet en mode avant et en lecture seule, les fonctions suivantes peuvent également être utilisées.
| Nom constant | La description | 
|---|---|
| CONCUR_READ_ONLY | Mode de traitement parallèle pour les objets ResultSet qui ne peuvent pas être mis à jour | 
| CONCUR_UPDATABLE | Mode de traitement parallèle des objets resultSet qui peuvent être mis à jour | 
| TYPE_FORWARD_ONLY | Le type d'objet ResultSet dans lequel le curseur se déplace uniquement vers l'avant | 
| TYPE_SCROLL_INSENTIVE | Un type d'objet ResultSet qui peut faire défiler mais ne reflète pas les modifications apportées aux données de la base | 
| TYPE_SCROLL_SENSITIVE | ResultSet type d'objet qui peut faire défiler et reflète le dernier contenu de la base de données | 
Pour l'utiliser, spécifiez une constante dans l'argument de la méthode createStatement comme indiqué ci-dessous.
Statement stmt = connection.createStatement(
                     ResultSet.TYPE_SCROLL_INSENSITIVE, //Indiquez de ne pas modifier la base de données dans le sens avant ou arrière
                     ResultSet.CONCUR_READ_ONLY //Ne peut pas être mis à jour, spécifier comme référence uniquement
                     )
[Remarques]
Cela dépend également de l'implémentation de JDBC (Oracle, PostgreSQL, MySQL, etc.) implémentée par le produit DB.
Par exemple, pour MySQL, le pilote JDBC (mysql-connector-java-5.1.42.jar) ne prend en charge que TYPE_SCROLL_INSENSITIVE.
Même s'il est spécifié, il devient un objet ResultSet défilable implicitement.
import java.sql.*;
public class JDBCGetMetaDataSample {
    public static void main(String[] args) {
        try (Connection connection = DbConnector.getConnect()) {
            DatabaseMetaData metaData = connection.getMetaData();
            System.out.println("TYPE_SCROLL_SENSITIVE: " + metaData.supportsResultSetType(
                    ResultSet.TYPE_SCROLL_SENSITIVE));
            System.out.println("TYPE_SCROLL_INSENSITIVE: " + metaData.supportsResultSetType(
                    ResultSet.TYPE_SCROLL_INSENSITIVE));
            System.out.println("TYPE_FORWARD_ONLY: " + metaData.supportsResultSetType(
                    ResultSet.TYPE_FORWARD_ONLY));
            System.out.println("CONCUR_READ_ONLY: " + metaData.supportsResultSetType(
                    ResultSet.CONCUR_READ_ONLY));
            System.out.println("CONCUR_UPDATABLE: " + metaData.supportsResultSetType(
                    ResultSet.CONCUR_UPDATABLE));
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
TYPE_SCROLL_SENSITIVE: false
TYPE_SCROLL_INSENSITIVE: true
TYPE_FORWARD_ONLY: false
CONCUR_READ_ONLY: false
CONCUR_UPDATABLE: false
mysql> select * from department;
+-----------+-------------+--------------+--------------+
| dept_code | dept_name   | dept_address | pilot_number |
+-----------+-------------+--------------+--------------+
|         1 | Sales       | Tokyo        | 03-3333-xxxx |
|         2 | Engineer    | Yokohama     | 045-444-xxxx |
|         3 | Development | Osaka        | NULL         |
|         4 | Marketing   | Fukuoka      | 092-222-xxxx |
|         5 | Education   | Tokyo        | NULL         |
|         6 | Plannning   | Yokohama     | 909-000-0000 |
|         7 | Planning    | Yokohama     | 055-555-5555 |
+-----------+-------------+--------------+--------------+
7 rows in set (0.00 sec)
Essayez la méthode de déplacement du curseur pour ceux-ci.
import java.sql.*;
public class JDBCCursorMoveSample {
    public static void main(String[] args) {
        //Triez par ordre croissant pour faciliter la compréhension des résultats.
        String sql = "SELECT dept_code, dept_name FROM department ORDER BY dept_code";
        try (Connection con = DbConnector.getConnect();
             Statement stmt = con.createStatement(
                     ResultSet.TYPE_SCROLL_INSENSITIVE,
                     ResultSet.CONCUR_UPDATABLE);
             ResultSet rs = stmt.executeQuery(sql)) {
            //Déplacer le curseur sur la dernière ligne
            rs.absolute(-1);
            System.out.format("cursor: %d, dept_code: %d, dept_name: %s\n",
                    rs.getRow(), rs.getInt(1), rs.getString(2));
            //Déplacer le curseur au début
            rs.absolute(1);
            System.out.format("cursor: %d, dept_code: %d, dept_name: %s\n",
                    rs.getRow(), rs.getInt(1), rs.getString(2));
            //Déplacer le curseur sur la dernière ligne
            rs.last();
            System.out.format("cursor: %d, dept_code: %d, dept_name: %s\n",
                    rs.getRow(), rs.getInt(1), rs.getString(2));
            //Déplacez le curseur sur la ligne suivant la dernière ligne
            rs.afterLast();
            System.out.format("cursor: %d\n", rs.getRow());
            //Déplacer le curseur au début
            rs.first();
            System.out.format("dept_code: %d, dept_name: %s\n",
                    rs.getInt(1), rs.getString(2));
            //Déplacez le curseur sur la ligne avant le début
            rs.beforeFirst();
            System.out.format("cursor: %d\n", rs.getRow());
            //Passez à la ligne suivante après la dernière ligne, puis faites défiler dans la direction opposée
            rs.afterLast();
            System.out.println("Résultat de sortie par défilement inversé----");
            while (rs.previous()) { //Défilement inversé
                System.out.format("dept_code: %d, dept_name: %s\n",
                        rs.getInt(1), rs.getString(2));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
Scala
Il n'y a pas de "try-with-resources" dans Scala, donc Mettez-le en œuvre vous-même. ʻUse` pour définir et utiliser la méthode.
Tout d'abord, nous allons préparer un objet singleton qui implémente la méthode using.
La fonction f utilise la ressource pour faire quelque chose et
Lorsque le processus est terminé, la méthode close () est exécutée.
object LoanPattern {
  /**
    *en utilisant la méthode
    *Traitement à fermer lorsque le traitement est terminé
    *Essayez Java-catch-Méthode alternative de ressource
    *
    * @Une méthode qui appelle enfin close avec param resource
    * @param f Processus à exécuter en utilisant l'argument ressource
    * @Un type qui a un tparam Une méthode close
    * @valeur de retour de la fonction tparam B f
    */
  def using[A <: {def close() : Unit}, B](resource:A)(f:A=>B): B = {
    try {
      f(resource) //Exécution du traitement
    } finally {
      if (resource != null) resource.close()
    }
  }
Contient la valeur obtenue dans la classe de cas.
case class UserAccount(id: Long, firstName: String, lastName: String)
Trait DAO. Si vous souhaitez modifier le référentiel pour RDB ou KVS, héritez de cette caractéristique.
trait UserDao {
  //Obtenez tous les utilisateurs
  def getUsers(): Seq[UserAccount]
  //Obtenir l'utilisateur par identifiant
  def getById(id: Long): Option[UserAccount]
}
Classe d'implémentation. Cette fois, c'est MySQL.
/**
  *Classe d'implémentation UserDao
  *Connectez-vous à MySQL.
  */
class UserDaoOnMySQL extends UserDao {
  import java.sql._
  import scala.collection.mutable.ArrayBuffer
  import LoanPattern.using
  override def getUsers(): Seq[UserAccount] = {
    using(getConnection()) { dbResource =>
      val stmt = dbResource.createStatement()
      val rs = stmt.executeQuery("select * from customers")
      val arrayBuffer = ArrayBuffer[UserAccount]()
      while (rs.next()) {
        arrayBuffer += UserAccount(
          rs.getInt("id"),
          rs.getString("first_name"),
          rs.getString("last_name"))
      }
      arrayBuffer.toList
    }
  }
  override def getById(id: Long): Option[UserAccount] = {
    using(getConnection()) { dbResource =>
      val stmt = dbResource.createStatement()
      val rs = stmt.executeQuery(s"select * from customers where id = ${id}")
      val arrayBuffer = ArrayBuffer[UserAccount]()
      while (rs.next()) {
        arrayBuffer += UserAccount(
          rs.getInt("id"),
          rs.getString("first_name"),
          rs.getString("last_name"))
      }
      arrayBuffer.find(_.id == id)
    }
  }
  private def getConnection() = 
    DriverManager.getConnection("jdbc:mysql://localhost/db", "username", "password")
}
Le côté utilisateur.
object SampleLoanPatternApp extends App {
  val dao = new UserDaoOnMySQL
  println(dao.getUsers())
  println(dao.getById(1))
}
        Recommended Posts