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