Il existe encore de nombreuses sources Java qui n'ont d'autre choix que de réaliser des connexions JDBC héritées. Cela peut être l'un des problèmes des programmeurs. S'il ne s'agit que de maintenance, vous devrez peut-être en créer un nouveau.
Comme cas qui vient immédiatement à l'esprit dans le sens de l'héritage Il se présente sous la forme de "mappage des informations extraites de la base de données avec Select comme bean" Le processus de traitement est ** encore cool ** mou ...
"Conserver les résultats de la requête une fois dans ResultSet" "Tournez le curseur de ResultSet pour remplir le bean" "Boucler les beans pour implémenter la logique métier" C'est comme ça.
La conception et la définition de SQL et Bean sont correctes, mais dans le processus Il arrive souvent que le tout reste bloqué simplement en faisant une erreur imprudente.
Plus intuitivement, ** N'est-il pas complet avec juste SQL et Bean? ** Ceci est l'article.
Comme le dit le titre. Strictement parlant, le "type de bean retourné" doit être spécifié à l'avance. Est-il proche de ** Ma bouteille de Starba **? Lorsque vous passez une commande (SQL) et donnez ma bouteille (Bean) à l'employé Ma bouteille est remplie de café et revient.
Vous pouvez le voir en regardant le code qui sort après cela. Il y a une partie qui ** ignore complètement ** la "sécurité de type", qui est l'une des fonctionnalités majeures de Java. Personnellement, c'est «séparé», mais les gens qui se font prendre peuvent se faire prendre. S'il vous plaît, pardonnez-moi.
[ORM](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83 % 88% E9% 96% A2% E4% BF% 82% E3% 83% 9E% E3% 83% 83% E3% 83% 94% E3% 83% B3% E3% 82% B0) n'est pas du tout détaillé. Donc, avec de meilleures fonctionnalités avec les intergiciels et les bibliothèques existants Il y a probablement des ressources qui font ce que je veux faire, Il y a aussi une conclusion qu'il y a de nombreuses opinions négatives plutôt que des avantages et des inconvénients de l'ORM lui-même. Bien que ce soit prématuré, j'ai arrêté de me pousser le cou de force. (Personnellement, ORM le reconnaît comme un mot ** large **, donc Je ne pense pas que tout soit mauvais C'est un fait que je déteste la chasse aux mots, alors je l'ai évité.)
L'article suivant est le plus proche de ce que je veux faire. La source de la pièce de base est détournée presque telle quelle. [Java] Créons une bibliothèque d'accès à la base de données!
Java 6 ou version ultérieure
Classe d'infrastructure de connexion de base de données et classe qui contrôle le mappage.
Une classe qui gère les espaces réservés qui sont des paramètres de SQL. Il s'agit d'un ** danger de type ** qui n'est pas de type sécurisé.
L'instruction SQL que vous souhaitez exécuter. Indépendamment de CRUD, il n'est pas nécessaire de le rendre persistant en tant que fichier ou enregistrement DB.
Classe Bean correspondant à la colonne d'extraction de Select. Créez-en un pour chaque instruction Select.
I/O Les E / S requises pour le fonctionnement minimum sont les suivantes.
-Le chemin complet de la classe du pilote JDBC (oracle.jdbc.driver.OracleDriver, etc.) -Connecteur JDBC (jdbc: oracle: thin: @ // localhost: 1521 / xe, etc.) -Utilisateur de connexion JDBC -Mot de passe de connexion JDBC ・ SQL -Paramètres SQL (cependant, non requis si les espaces réservés ne sont pas utilisés)
Bean
Il est basé sur les classes JDBCManager et SqlParameter.
Classe JDBCManager
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class JDBCManager {
private Connection conn;
@SuppressWarnings("unused")
private JDBCManager() throws Throwable{}
public JDBCManager(String driver,String url,String user,String password) throws ClassNotFoundException,SQLException{
Class.forName(driver);
this.conn = DriverManager.getConnection(url, user, password);
this.conn.setAutoCommit(false);
}
private void setParams(PreparedStatement statement, SqlParameter sqlParameter) throws SQLException {
if(sqlParameter == null || !sqlParameter.hasParameters()) {
return;
}
int paramNo = 1;
for( Object param : sqlParameter.toParameter() ) {
statement.setObject(paramNo++, param);
}
}
public void commit() throws SQLException{
this.conn.commit();
}
public void rollback() throws SQLException{
this.conn.rollback();
}
public void close() throws SQLException{
this.conn.close();
}
private <E> E toObject(ResultSet rs, Class<E> clazz) throws InstantiationException, IllegalAccessException, SQLException {
E bean = null;
if( rs.next() ) {
Field[] fields = clazz.getDeclaredFields();
bean = clazz.newInstance();
for (Field f : fields) {
f.setAccessible(true);
Object val = rs.getObject(f.getName());
f.set(bean, val);
}
}
return bean;
}
private <E> List<E> toObjectList(ResultSet rs, Class<E> clazz) throws SQLException, InstantiationException, IllegalAccessException {
List<E> rsList = new ArrayList<E>();
while (rs.next()) {
Field[] fields = clazz.getDeclaredFields();
E bean = clazz.newInstance();
for( Field f: fields ) {
f.setAccessible(true);
Object val = rs.getObject( f.getName() );
f.set(bean, val);
}
rsList.add(bean);
}
return rsList;
}
private SQLException sqlErr(Throwable e, CharSequence sql) {
return new SQLException("sql error!\nerror occurred sql="+sql, e);
}
public int insert(String sql, SqlParameter sqlParameter) throws SQLException {
return exert(sql,sqlParameter);
}
public int update(String sql, SqlParameter sqlParameter) throws SQLException {
return exert(sql,sqlParameter);
}
public int delete(String sql, SqlParameter sqlParameter) throws SQLException {
return exert(sql,sqlParameter);
}
private int exert(String sql, SqlParameter sqlParameter) throws SQLException {
PreparedStatement statement = null;
try {
statement = conn.prepareStatement(sql.toString());
setParams(statement,sqlParameter);
int ret = statement.executeUpdate();
return ret;
}catch (SQLException e){
throw sqlErr(e, sql);
}finally {
try {
if(statement != null){
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public <E> E selectOne(String sql, Class<E> clazz) throws SQLException {
return selectOne(sql,clazz,null);
}
public <E> E selectOne(String sql, Class<E> clazz, SqlParameter sqlParameter) throws SQLException {
ResultSet rs = null;
PreparedStatement statement = null;
try{
statement = conn.prepareStatement(sql.toString());
setParams(statement,sqlParameter);
rs = statement.executeQuery();
E val = toObject(rs, clazz);
return val;
}catch(Exception e) {
throw sqlErr(e, sql);
}finally {
try {
if( rs != null ) {
rs.close();
}
}catch(SQLException e) {
e.printStackTrace();
}finally {
try {
if(statement != null){
statement.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
}
}
}
public <E> List<E> selectList(String sql, Class<E> clazz) throws SQLException {
return selectList(sql,clazz,null);
}
public <E> List<E> selectList(String sql, Class<E> clazz, SqlParameter sqlParameter) throws SQLException {
ResultSet rs = null;
PreparedStatement statement = null;
try {
statement = conn.prepareStatement(sql.toString());
setParams(statement,sqlParameter);
rs = statement.executeQuery();
List<E> rsList = toObjectList(rs, clazz);
return rsList;
}catch(Exception e) {
throw sqlErr(e, sql);
}finally {
try {
if( rs != null ) {
rs.close();
}
}catch(SQLException e) {
e.printStackTrace();
}finally {
try {
if(statement != null){
statement.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
}
}
}
}
Classe SqlParameter
import java.util.ArrayList;
import java.util.List;
public class SqlParameter {
@SuppressWarnings("rawtypes")
private List list = null;
@SuppressWarnings("rawtypes")
public SqlParameter(int paramNumber){
list = new ArrayList(paramNumber);
}
@SuppressWarnings("rawtypes")
public SqlParameter(){
list = new ArrayList();
}
@SuppressWarnings("unchecked")
public <E> void addParameter(E e){
list.add(e);
}
public boolean hasParameters() {
return list.size()==0 ? false : true;
}
public Object[] toParameter(){
return list.toArray();
}
}
Je vais le proposer dans quatre cas. La base de données cible est "Oracle (Express Edition)". Les cibles de l'opération sont les tables "EMP" et "DEPT" qui existent par défaut dans le schéma.
(1) Sélectionnez: SQL d'acquisition multiple sans clause WHERE (aucun espace réservé requis) (2) Sélectionnez: Obtenir plusieurs enregistrements avec clause WHERE (avec espace réservé) SQL ③ Sélectionnez: SQL d'acquisition unique ④ Mettre à jour (insérer, mettre à jour, supprimer)
Nous allons créer des beans en fonction de chaque SQL. Le but est de rendre le ** alias (AS) de Select et le nom de champ du bean identiques **.
Déclarez également le type de champ bean dans une classe selon la spécification JDBC.
Dans Select of this sample, nous opérons sur une seule table. Le même processus peut être effectué avec Select pour plusieurs tables en utilisant ** join **.
Le point est "** C'est bien si SQL et Bean correspondent **".
Select_SQL d'acquisition multiple sans clause WHERE (aucun espace réservé requis)
SELECT
--VARCHAR2
DNAME AS dname
FROM
DEPT
Classe DeptBean
public class DeptBean {
private String dname = null;
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
Select_Obtenir plusieurs enregistrements avec clause WHERE (avec espace réservé) SQL
SELECT
--NUMBER
EMPNO AS empNo,
--VARCHAR2
ENAME AS ename,
--DATE
HIREDATE AS hireDate
FROM
EMP
WHERE
DEPTNO = ?
AND
JOB = ?
Classe EmpBean
import java.math.BigDecimal;
import java.sql.Timestamp;
public class EmpBean {
private BigDecimal empNo = null;
private String ename = null;
private Timestamp hireDate = null;
public BigDecimal getEmpNo() {
return empNo;
}
public void setEmpNo(BigDecimal empNo) {
this.empNo = empNo;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public Timestamp getHireDate() {
return hireDate;
}
public void setHireDate(Timestamp hireDate) {
this.hireDate = hireDate;
}
}
Select_SQL de capture unique
SELECT
--NUMBER
EMPNO AS empNo,
--VARCHAR2
ENAME AS ename,
--DATE
HIREDATE AS hireDate
FROM
EMP
WHERE
//PK
EMPNO = ?
Classe EmpBean
(Comme c'est le même que ci-dessus, il est omis)
Utilisons insert comme exemple. Vous n'avez pas besoin de créer un bean pour la mise à jour car le résultat est reçu en tant que int.
insert
INSERT INTO DEPT
--NUMBER,VARCHAR2,VARCHAR2
(DEPTNO, DNAME, LOC)
values
(?, ?, ?)
Je vais déplacer les quatre cas ci-dessus.
Classe d'essai
import java.math.BigDecimal;
import java.util.List;
public class JDBCTest {
public static void main(String[] args) throws Throwable{
JDBCTest t = new JDBCTest();
t.execute();
}
public void execute() throws Throwable{
//Informations de connexion JDBC
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@//localhost:1521/xe";
String user = "ouser";
String password = "ouser";
//Initialiser le gestionnaire JDBC
JDBCManager jdbc = new JDBCManager(driver,url,user,password);
//Modèle 1. SQL d'acquisition multiple sans clause WHERE (aucun espace réservé requis)
String sql = "SELECT "
+ "DNAME AS dname "
+ "FROM "
+ "DEPT ";
//Obtenir la liste
List<DeptBean> dlist = jdbc.selectList(sql, DeptBean.class);
System.out.println("――― Modèle 1 ―――");
for(DeptBean d : dlist) {
System.out.println(d.getDname());
}
//Modèle 2. Obtenir plusieurs enregistrements avec clause WHERE (avec espace réservé) SQL
//Ajuster au champ bean avec alias
sql = "SELECT "
+ "EMPNO AS empNo, "
+ "ENAME AS ename, "
+ "HIREDATE AS hireDate "
+ "FROM "
+ "EMP "
+ "WHERE "
+ "DEPTNO = ? "
+ "AND "
+ "JOB = ? ";
//Deux espaces réservés
SqlParameter p = new SqlParameter(2);
//Lier dans l'ordre depuis le début
p.addParameter(new BigDecimal(30));
p.addParameter("SALESMAN");
//Obtenir la liste
List<EmpBean> elist = jdbc.selectList(sql, EmpBean.class, p);
System.out.println("――― Modèle 2 ―――");
for(EmpBean e : elist) {
System.out.println(e.getEmpNo() + "\t" + e.getEname() + "\t" + e.getHireDate());
}
//Modèle 3. SQL de capture unique
sql = "SELECT "
+ "EMPNO AS empNo, "
+ "ENAME AS ename, "
+ "HIREDATE AS hireDate "
+ "FROM "
+ "EMP "
+ "WHERE "
//PK
+ "EMPNO = ? ";
p = new SqlParameter(1);
p.addParameter(new BigDecimal(7369));
//Obtenez Bean
EmpBean emp = jdbc.selectOne(sql, EmpBean.class, p);
System.out.println("――― Modèle 3 ―――");
System.out.println(emp.getEname());
//Modèle 4. Mettre à jour (insérer,update,delete)
sql = "INSERT INTO DEPT "
+ "(DEPTNO, DNAME, LOC) "
+ "values "
+ "(?, ?, ?) ";
p = new SqlParameter(3);
p.addParameter(new BigDecimal(99));
p.addParameter("SPECIAL");
p.addParameter("JAPAN");
int i = jdbc.insert(sql, p);
System.out.println("――― Modèle 4 ―――");
System.out.println("Le nombre d'insertions"+i+"C'est une question");
jdbc.commit();
//En fait, intercepter une erreur et attraper jdbc.rollback()Courir
jdbc.close();
//En fait, il piège une erreur et enfin jdbc.close()Courir
}
}
Le résultat de l'exécution est le suivant.
Résultat d'exécution (sortie standard)
――― Modèle 1 ―――
ACCOUNTING
RESEARCH
SALES
OPERATIONS
――― Modèle 2 ―――
7499 ALLEN 1981-02-20 00:00:00.0
7521 WARD 1981-02-22 00:00:00.0
7654 MARTIN 1981-09-28 00:00:00.0
7844 TURNER 1981-09-08 00:00:00.0
――― Modèle 3 ―――
SMITH
――― Modèle 4 ―――
Le nombre d'insertions est de 1.
Même si vous comparez à partir de l'article auquel j'ai fait référence Il n'y a presque pas de nouveau contenu, Le risque de provoquer une erreur d'exécution est augmenté car il n'est pas de type sécurisé. Personnellement, je gère au plus trois cibles, ** SQL **, ** paramètres ** et ** Bean **. S'il s'agit de jouer avec Resultset et de prendre du temps Je pense que cela vaut le compromis pour la sécurité de type.
De plus, dans un environnement où Java ne peut pas être mis à niveau pour diverses raisons, Dans un environnement où le middleware basé sur la base de données et les bibliothèques telles que ORM ne peuvent pas être installés, Même s'il y a des restrictions environnementales et opérationnelles J'aime le fait qu'il ne peut fonctionner qu'avec les anciennes VM Java **.
Cette fois, j'ai ciblé Oracle comme base de données Si vous pouvez vous connecter avec JDBC, il existe des différences de comportement dialectiques. Je suis optimiste que n'importe quelle base de données peut être utilisée.