En el blog anterior propuse encapsular la conectividad, primero para esconder algún nivel de complejidad, y segundo con el propósito de construir una estructura reutilizable para más de un sistema de base de datos
La estructura propuesta (gráfico) tiene que ver con una clase abstracta que contine la lógica pre-elaborada y normalizada para lograr un punto de comunicación con cualquier sistemas de base de datos RDBMS que "hable" JDBC. El usuario de esta clase utilizará el método connect(...) para logar una conexión activa, internamente se llama al método setServer(..) a ser definido en una subclase concreta orientada a un RDBMS específico, en nuestro caso las clases concretas son SQLSERVERConnection y MySqlConnection, para SqlServer y MySql respectivamente.
1 ... 2 // Conectividad abstracta 3 abstract class Connection { 4 5 abstract void setServer(server,DB) 6 7 boolean connect(erver,DB,user,password) { 8 ... 9 setServer(server,DB) 10 ... 11 } 12 ... 13 } 14 15 16 // Conectividad MS-SqlServer 17 class SQLSERVERConnection extends Connection { 18 19 void setServer(server,DB) { 20 ... 21 } 22 23 } 24 25 26 // Conectividad MySQL 27 class MySqlConnection extends Connection { 28 29 void setServer(server,DB) { 30 ... 31 } 32 33 }
Como se vió en el blog anterior las subclases concretas se limitan a definir los campos driver y url de acuerdo a cada RDBMS. Si desea conectarse a Oracle, primero deberá encontrar e instalar las librerías de conectividad JDBC, agregar a CLASSPATH la localización de los archivos JAR y luego crear la clase concreta que la podriamos llamar OracleConnection.
Para lograr un buen nivel de adaptabilidad, una "factoría" parece lo más indicado. Esta no es otra cosa que una clase con un método estático, en este caso getConnection(...), que retorna una instancia de una conexión específica.
1 class ConnectionFactory { 2 3 static Connection getConnection(dbType) { 4 if(dbType == 'MySQL') 5 return new MySqlConnection() 6 else 7 if(dbType == 'MS-SqlServer') 8 return new SQLSERVERConnection() 9 else 10 return null ; 11 } 12 13 }
Honestamente ésta es una factoría bastante simple. La idea es que en base al argumento el método retorne una instancia de conexión específica
1 // recupera una conexión para MySql 2 Connection cn = ConnectionFactory.getConnection('MySql') 3 4 // recupera una conexión para SqlServer 5 Connection cn = ConnectionFactory.getConnection('MS-SqlServer')
A continuación se presenta el código completo, al final hay un código de prueba, que deberá ser comentado o eliminado luego de las respectivas pruebas. Este código lo he guardado en un archivo de nombre DBConection.groovy.
1 import groovy.sql.Sql 2 3 4 // == Abstract connection == 5 6 abstract class Connection { 7 8 def db 9 10 def driver 11 12 def url 13 14 abstract void setServer(strServer,strDB) 15 16 boolean connected = false 17 18 boolean connect(strServer,strDB,strUser,strPassword) { 19 try { 20 if(connected) 21 disconnect() 22 setServer(strServer,strDB) 23 db = Sql.newInstance(url,strUser,strPassword,driver) 24 connected = true 25 26 } catch(Exception ex) { 27 db = null 28 connected = false 29 } 30 31 return connected 32 } 33 34 35 void disconnect() { 36 db.close() 37 db = null 38 } 39 40 } 41 42 43 // == MS-SqlServer connection == 44 45 class SQLSERVERConnection extends Connection { 46 47 void setServer(strServer,strDB) { 48 driver = 'com.microsoft.jdbc.sqlserver.SQLServerDriver' 49 url = "jdbc:microsoft:sqlserver://$strServer:1433;databaseName=$strDB" 40 } 51 52 } 53 54 55 // == MySQL connection == 56 57 class MySqlConnection extends Connection { 58 59 void setServer(strServer,strDB) { 60 driver = 'com.mysql.jdbc.Driver' 71 url = "jdbc:mysql://$strServer:3306/$strDB" 72 } 73 74 } 75 76 77 // === Factory Class === 78 79 class ConnectionFactory { 80 81 static Connection getConnection(dbType) { 82 if(dbType == 'MySQL') 83 return new MySqlConnection() 84 else 85 if(dbType == 'MS-SqlServer') 86 return new SQLSERVERConnection() 87 else 88 return null ; 89 } 90 91 } 92 93 94 95 // - código de prueba : inicio 96 97 def myServer = 'localhost' 98 def myDBType = 'MySQL' 99 def myUser = 'root' 100 def myPassword = 'admin' 101 102 Connection myConection = ConnectionFactory.getConnection(myDBType) 103 104 if(myConection.connect(myServer,myDBType,myUser,myPassword)) { 105 println '¡ Bacán ! me conecté a $myDBType en $myServer !!!' 106 myConection.disconnect() 107 } 108 else 109 println 'uff... no pude Conectarme a $myDBType en $myServer ' 110 111 return true // - código de prueba : fin
Para compilar estas clases almacenadas en el archivo "DBConection.groovy", procedo desde la línea de comandos:
groobyc DBConection.groovy
que genera un archivo *.class por cada clase
Para "los iniciados"...
...estoy totalmente de acuerdo que:
- es posible evitar la herencia si leemos parámetros de un archivo de configuración
- es necesario declarar una interface con el contrato de implementación
- es posible y necesario parametrizar los puertos IP
- si se soporta en Hibernate, IBatis, etc. puede que Ud. esté haciendo las cosas de otra manera