Chargement driver JDBC dynamique et introspection

aashintan Messages postés 6 Date d'inscription lundi 2 novembre 2009 Statut Membre Dernière intervention 14 janvier 2010 - 2 nov. 2009 à 19:34
aashintan Messages postés 6 Date d'inscription lundi 2 novembre 2009 Statut Membre Dernière intervention 14 janvier 2010 - 4 nov. 2009 à 12:12
Bonjour à tous,

Je développe actuellement une petite application Java SE (1.6) qui se sert d'une base de données embarquée Derby. Actuellement, la communication avec cette base fonctionne correctement. Cependant, je destine cette application à une évolution majeure, à savoir : pouvoir communiquer avec différent type de base de données (MySql, DB2, Oracle).

Le problème qui se pose alors est que le SQL est spécifique à chaque type de base de données (différence de syntaxe, mots clés, etc.) et qu'il me faut donc redéfinir pour chaque type de base de données les méthodes de traitement (ex : ajouter une colonne, insérer / supprimer une ligne, créer une table, etc.)

A la base je comptais créer une interface listant les méthodes de traitement et créer autant de classe que de driver mis à disposition (j'en choisirais 2 pour commencer).

Cependant, bon nombre de méthodes sont redondantes, notamment toutes celles liées aux traitements sur les objets ResultSet. Cette première solution n'est donc pas bonne, ou du moins pas optimale.

Ensuite j'ai bien essayé de transformer mon interface en bête classe afin de pouvoir y mettre du code, cependant, tout comme il n'est pas permis de mettre du code (body) dans une interface, il n'est pas possible de définir des méthodes abstraites dans une classe.

Finalement, je me suis rabattu sur un système d'introspection ou le code va chercher le morceaux d'algorithme dont il a besoin la ou il faut. Mais c'est très lourd.

N'y aurait-il pas une autre solution ?

Merci d'avance,

Aash.

3 réponses

cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
2 nov. 2009 à 20:02
Salut,

Il te suffit de faire des classes utilitaires contenant le code en commun (des méthodes public static dans une classes abstraite), ou à la limite, une classe abstraite qui implémente ton interface, puis de faire dériver tes classes concrètes de ses classes abstraites (mais à ce moment là, tu ne pourras plus faire hériter tes classes d'une autre classe).

Il est parfaitement possible de faire des méthodes abstraites dans une classe, mais celle-ci doit alors elle aussi être abstraite du coup !
______________________________________
DarK Sidious
0
aashintan Messages postés 6 Date d'inscription lundi 2 novembre 2009 Statut Membre Dernière intervention 14 janvier 2010
2 nov. 2009 à 22:12
Mais c'est bien sur, j'avais complétement oublié les classes abstraites, je partais directement dans les interfaces. A force de rester le nez dessus je ne voyais plus rien.

En tout cas merci bien, je vais voir ce que je peux faire avec ca.
0
aashintan Messages postés 6 Date d'inscription lundi 2 novembre 2009 Statut Membre Dernière intervention 14 janvier 2010
4 nov. 2009 à 12:12
Je reviens sur ce que j'ai dis, même en séparant le code spécifique à chaque type de base (Derby, Oracle, etc.) il y a de la redondance entre chacune de ces classes, notamment pour le traitement des ResultSet et l'exécution des requêtes SQL.

J'ai donc choisi de créer une classe Database qui comporte toutes les méthodes dont j'ai besoin, et qui instancie un objet spécifique au type de base à sa construction. Cette objet est une classe dont les méthodes vont retourner la requête SQL correcte pour chaque méthode de Database.

Voici un bout de ma classe spécifique :

public class DerbyDatabase {
/**
* Apache Derby DB driver.
*/
private final String driver = "org.apache.derby.jdbc.EmbeddedDriver";

/**
* @param stTableName : name of the table to proceed insert
* @param stColumnName : name of the column to add
* @return a String containing the SQL query
*/
public final String getAddColumnQuery(final String stTableName, final String stColumnName) {
String colName = stTableName.substring(2, Database.C_TABLE_NAME_INDEX) + "_" + stColumnName.toUpperCase();
String addColumnSQL = "ALTER TABLE " + Database.NAME_SCHEMA + "." + stTableName + " ADD COLUMN " + colName + " VARCHAR(50)";
return addColumnSQL;
}
/**
* @return the driver class name
*/
public final String getDriverName() {
return driver;
}
}


Et voici comment je m'en sers dans ma classe Database :

public class Database {
/**
* Logger.
*/
private static Logger log = Logger.getLogger(Database.class.getName());
/**
* Appropriate interface according to DB type.
*/
private DatabaseInterface dbi;
/**
* Name of the DB.
*/
private final String dbName;

/**
* @param stDbType : type of the DB
* @param stDbName : name of the DB
*/
public Database(final String stDbType, final String stDbName) {
try {
dbi = (DatabaseInterface) Class.forName(StringUtils.capitalize(stDbType) + "Database").newInstance();
Class.forName(dbi.getDriverName());
} catch (InstantiationException e) {
log.error("Cannot instanciate class for DB of type : " + stDbType + ". " + e);
} catch (IllegalAccessException e) {
log.error("Access not permitted. " + e);
} catch (ClassNotFoundException e) {
log.error("No class defined for DB of type : " + stDbType + ". " + e);
}
dbName = stDbName;
}

/**
* @param stTableName : name of the table where proceeding insert
* @param stColumnName : name of the column to add
* @return true if operation performs
*/
protected final boolean addColumn(final String stTableName, final String stColumnName) {
// Parameters test - START
if (stTableName null || stTableName.length() 0 || stColumnName == null
|| stColumnName.length() == 0) {
log.error("Parameter(s) null or invalid");
return false;
}
// Parameters test - END
boolean addColumn = false;
if (connection != null) {
String addColumnSQL = dbi.getAddColumnSql(stTableName, stColumnName);
if (executeUpdate(addColumnSQL) > -1) {
addColumn = true;
}
}
return addColumn;
}

Évidemment je ne vous poste pas tout le code, il s'agit d'un morceaux que je trouve assez révélateur... Mais est-ce que dans l'ensemble c'est propre ?, la bonne façon de faire ?

Merci d'avance,

Aash.

PS : je n'est pas trouvé de balises
 
pour mettre ca en forme, désolé pour le post en vrac.
0
Rejoignez-nous