C贸mo configurar la conexi贸n a SQLServer mediante JDBC (NetBeans, Java 8, SQLServer Express 2016, Windows 10…)

Nunca antes, luego de haber aprendido c贸mo conectarme a distintas bases de datos mediante JDBC, me hab铆a costado tanto una como lo fue con SQLServer (casi 15 minutos). Gracias a Google, Stack聽Overflow y conocimiento previo sali贸 medianamente r谩pido, pero vamos, que a esta gente le gusta complicar a veces las cosas.

Archivo de propiedades de conexi贸n (config.properties)

Ya sabemos que es de muy mala educaci贸n, y prohibido adem谩s, hard-codear valores o atributos聽que pueden cambiar en el tiempo de una computadora, una red, etc… a otra; entre ellos las propiedades de conexi贸n a una base de datos. Es por eso, que lo ideal es colocarlo en un archivo de propiedades como los que estamos acostumbrados a hacer:

#Ubicado en src\res\config.properties
db.url=jdbc:sqlserver://servidor\\SQLEXPRESS;databaseName=nombre_bd;integratedSecurity=true
db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
db.user=usuario
db.password=clave

Respecto a los valores db.url y db.driver, recordemos que cada manejador de base datos 聽(o DBMS, como quieran llamarlo) tiene su forma de establecer estos valores, los que les indico funcionan con SQLServer Express 2016; ac谩 mucha mas informaci贸n respecto a c贸mo formar la url.

Y una clase en Java sencilla que lo lea:

package th.control.db;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
/**
 *
 * @author jescobar
 */
public final class DBConnection {
 static InputStream inputStream;
 static Connection conn;
 public static void connect() throws Exception {
 inputStream = Class.forName("th.control.db.DBConnection").getClassLoader().getResourceAsStream("config.properties");
 Properties prop = new Properties();
 prop.load(inputStream);
 Class.forName(prop.getProperty("db.driver"));
 conn = DriverManager.getConnection(
 prop.getProperty("db.url"),
 prop.getProperty("db.user"),
 prop.getProperty("db.password"));
 System.out.println("Me conect茅!!!");
 }
}

Todo bien, compila al pelo, pero al ejecutar un indeseado聽java.lang.NullPointerException te aparece en la l铆nea donde intentas cargar el archivo de propiedades mediante el m茅todo prop.load(inputStream).

run:
Exception in thread "main" java.lang.NullPointerException
 at java.util.Properties$LineReader.readLine(Properties.java:434)
 at java.util.Properties.load0(Properties.java:353)
 at java.util.Properties.load(Properties.java:341)
 at th.control.db.DBConnection.connect(DBConnection.java:26)

El punto es que ni NetBeans ni Eclipse te van a decir d贸nde colocar el archivo para que sea le铆do, debes especificar en cada IDE que rutas incluir en el classpath. En NetBeans una soluci贸n sencilla es moverlo al directorio src.

#Ubicado en src
db.url=jdbc:sqlserver://servidor\\SQLEXPRESS;databaseName=nombre_bd;integratedSecurity=true
db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
db.user=usuario
db.password=clave

Ahora tu problema va a ser otro…

Colocando donde es el Driver de conexi贸n

Yo estoy partiendo de que ya te hab铆as descargado el driver JDBC de Microsoft, bien sea el sqljdbc41.jar o el sqljdbc42.jar (clic ac谩 si no lo has hecho) para conectarte con su BD, creaste un directorio lib en el proyecto, y ah铆 lo metiste. Pero al tratar de ejecutar, recibes otro mensaje de que no vas…

run:
Exception in thread "main" java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:264)
 at th.control.db.DBConnection.connect(DBConnection.java:29)

Y es que tienes que decirle a NetBeans donde estas colocando tus librer铆as externas. Algo as铆 logras presionando sobre el bot贸n 芦Add JAR/Folder禄 y especificando la ruta聽que visualizas en la imagen.

002

Y con lo anterior, al tratar de ejecutar… Cambiamos de problema! Uno mas de no sabemos cuantos mas… Pero lo que si sabemos, que como todo, es que en alg煤n momento ya no habr谩n.

Ahora la librer铆a que colocamos nos est谩 diciendo que no logra conectarse con el servidor SQLServer…

run:
Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: No se pudo realizar la conexi贸n TCP/IP al host localhost, puerto 1433. Error: "Connection refused: connect. Verifique las propiedades de conexi贸n, compruebe que hay una instancia de SQL Server ejecut谩ndose en el host y aceptando las conexiones TCP/IP en el puerto y compruebe que no hay ning煤n firewall bloqueando las conexiones TCP en el puerto.".
 at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:191)
 at com.microsoft.sqlserver.jdbc.SQLServerException.ConvertConnectExceptionToSQLServerException(SQLServerException.java:242)
 at com.microsoft.sqlserver.jdbc.SocketFinder.findSocket(IOBuffer.java:2369)
 at com.microsoft.sqlserver.jdbc.TDSChannel.open(IOBuffer.java:551)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1963)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1628)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1459)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:773)
 at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
 at java.sql.DriverManager.getConnection(DriverManager.java:664)
 at java.sql.DriverManager.getConnection(DriverManager.java:247)
 at th.control.db.DBConnection.connect(DBConnection.java:30)

Acomodando las cosas para que SQLServer escuche

No tiene sentido que si usas el Microsoft SQL Server Management Studio, y ah铆 puedes hacer lo que te plazca (creates, updates, inserts, tanto de datos como esquemas, bases de datos, etc…) si tratas de conectarte desde otra aplicaci贸n, est茅n las puertas cerradas. Para abrirlas hay que hacer lo siguiente:

En una l铆nea de comandos (cmd), o desde el comando ejecutar (Tecla Win + R), ejecuta los siguiente:

 C:\Windows\SysWOW64\SQLServerManager13.msc

Se te abrir谩 una ventana como la siguiente (yo ni sab铆a que exist铆a). Es el SQL Server Configuration Manager.

001

Y tal como muestra la imagen siguiente, habilita las comunicaci贸n TCP/IP dentro de Protocolos de SQLEXPRESS.

003

El SQL Server Configuration Manager te va a decir que necesitas reiniciar el servicio para que los cambios tomen efecto, la siguiente imagen te indica c贸mo hacerlo.

004

Le damos play a la clase y…. Otra excepci贸n… Lo bueno es que esta nos dice expl铆citamente que hacer!

run:
Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: No se pudo realizar la conexi贸n con el host localhost, instancia con nombre sqlexpress. Error: "java.net.SocketTimeoutException: Receive timed out". Verifique los nombres del servidor y de instancia, compruebe que no hay ning煤n firewall bloqueando el tr谩fico UDP al puerto 1434. Para SQL Server 2005 o posterior, verifique que el servicio SQL Server Browser se est谩 ejecutando en el host.
 at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:191)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.getInstancePort(SQLServerConnection.java:5247)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.primaryPermissionCheck(SQLServerConnection.java:1871)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1608)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1459)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:773)
 at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
 at java.sql.DriverManager.getConnection(DriverManager.java:664)
 at java.sql.DriverManager.getConnection(DriverManager.java:247)
 at th.control.db.DBConnection.connect(DBConnection.java:30)

Nos dice que verifiquemos que un fulano servicio llamado SQL Server Browser debe estar iniciado. Y si revisamos la 煤ltima imagen, hay algo ah铆 llamado igual. No hace falta imagen para esto sino sentido com煤n: Clic derecho -> Iniciar… Play de nuevo!

run:
feb 05, 2017 9:59:38 AM com.microsoft.sqlserver.jdbc.AuthenticationJNI <clinit>
ADVERTENCIA: Failed to load the sqljdbc_auth.dll cause : no sqljdbc_auth in java.library.path
Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: Este controlador no est谩 configurado para la autenticaci贸n integrada. ClientConnectionId:056b6f27-b750-4a8d-bda7-188d11f2aae9
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:2400)
 at com.microsoft.sqlserver.jdbc.AuthenticationJNI.<init>(AuthenticationJNI.java:68)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.logon(SQLServerConnection.java:3132)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.access$100(SQLServerConnection.java:43)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection$LogonCommand.doExecute(SQLServerConnection.java:3123)
 at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7505)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2445)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1981)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1628)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1459)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:773)
 at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
 at java.sql.DriverManager.getConnection(DriverManager.java:664)
 at java.sql.DriverManager.getConnection(DriverManager.java:247)
 at th.control.db.DBConnection.connect(DBConnection.java:30)

Ok, esto sigue descontrolado! Y ahora qu茅?

Bueno, resulta que Microsoft permite dos maneras de conectarnos con su base de datos, y eso se lo decimos en el archivo de configuraci贸n. El par谩metro聽integratedSecurity (integratedSecurity=true) indica si se usan las credenciales de Windows para conectarnos o si por el contrario, debemos especificar un usuario o contrase帽a (integratedSecurity=false), tal cual estamos haciendo. En otras palabras, SQLServer se esta pasando por el forro nuestro usuario y clave porque est谩 usando nuestras credenciales de Windows para iniciar sesi贸n…

Hay dos soluciones para esto… La que puedes inferir en el p谩rrafo anterior (coloca en false el valor de integratedSecurity), o la otra, localizar el bendito聽sqljdbc_auth.dll y pegarlo en la carpeta System32 de Windows. Ambas funcionan, y el fulano .dll est谩 en el mismo archivo donde bajaste los drivers JDBC de SQL Server hace unos parrafos mas arriba.

Cuando ejecutes de nuevo tu clase, este ser谩 el mensaje que obtendr谩s:

run:
Me conect茅!!!

Saludos!

Una respuesta a 芦C贸mo configurar la conexi贸n a SQLServer mediante JDBC (NetBeans, Java 8, SQLServer Express 2016, Windows 10…)禄

Deja un comentario

Tu direcci贸n de correo electr贸nico no ser谩 publicada.