Foro sobre Java SE > Conexion con Base de datos
Lo mas fácil es crear una clase para obtener un objeto Connection, por ejemplo llamada Conexion.
Podría ser algo así...
public class Conexion{
static String user="usuarioBBDD";
static String pass="passwordBBDD";
static String bbdd="nombreBBDD";
static String ipServer="ipServidorBBDD";
static String urlCon="jdbc:mysql://"+ipServer+"/"+bbdd;
static Connection conn;
public static Connection getConnection(){
if(conn==null){
try
{
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e)
{
e.printStackTrace();
}
try {
conn=DriverManager.getConnection(urlCon,user, pass);
} catch (SQLException ex) {
ex.printStackTrace();
}
return conn;
}
else{
return conn;
}
}
}
El ejemplo es sobre mysql, pero dependiendo de tu gestor cargaras un driver u otro. Tras crear esa clase, simplemente después cuando necesites un objeto Connection en alguna de las interfaces para realizar operaciones sobre la bbdd, solo tendrías que hacer:
Connection conn=Conexion.getConnection();
//Todas las operaciones que quieras en la bbdd usando este objeto conexion
Hay un millón de maneras de hacerlo, pero creo que esta es de las mas sencillas.
No sé apenas de JDBC, pero aquí tienes algunas ideas:
* Extrae el código que hace la conexión y, en general, interactúa con la base de datos a una o varias clases separadas. Esto es lo que te acaba de contestar loderain mientras yo preparaba mi respuesta. :-)
* Para disponer de múltiples conexiones, utiliza el interface PooledConnection.
* Busca en Internet información sobre el patrón de Java EE DAO (casi seguro que en la documentación de JavaHispano también tienes algo). Ese patrón te sirve para aislar la gestión de la persistencia (en tu caso, del acceso a la base de datos) del manejo de los objetos dentro del resto del programa, lo que permite que el grueso de tu aplicación no tenga que saber si guardas en una base de datos SQL, un archivo de texto o haces llamadas a un servicio web para leer y escribir los datos en una base de datos remota.
Ten en cuenta que, si usas varias conexiones simultáneas, lo que hace una puede no verlo la otra hasta que refrescas (o, a lo mejor, hasta que fuerzas el vaciado de caché de cada conexión; esto no lo sé seguro con JDBC, pero con JPA sí pasa).
Hola, en cuanto a la comunicación entre clases puedes hacerlo de dos maneras, la primera es Heredando una clase de otra, la segunda es realizando instancias de clase. Te recomiendo usar instancias de clase (Es herencia básica) y es la que te explicaré:
Supongamos que tienes 3 clases:
1. Login: Para inicio de sesión de usuarios y registro.
2. Conexión: Para realizar la conexión con la base de datos.
3. Usuario: Esta clase contiene los métodos para registrar, modificar, eliminar o consultar un usuario en la base de datos.
Clase Conexion (debes importar las clases necesarias y la librería JDBC):
public class Conexion {
private final String URL = "jdbc:mysql://localhost/nombreBD"; //Dirección de la base de datos
private final String USUARIO= "root"; //Usuario de MySQL, generalmente root
privete final String CONTRASEÑA = "" //Contraseña del root en caso de tenerla
private Connection Conector; //Variable que almacenará la conexión.
public Conexion { //Se define un constructor para la clase
Conector = null; //Inicialización de la conexión para asegurarse de que aun no hay conexión.
}
//Función que retornará la conexión:
public Connection Conectar(){
//Encerrar en bloque try - catch() para capturar posibles excepciones:
try{
Class.forName("com.mysql.jdbc.Driver"); //Importante para incluir la librería de JDBC y el driver de la conexión
Conector = DriverManager.getConnection(URL, USUARIO, CONTRASEÑA); //Intentar realizar la conexión y almacenarla en la variable conector.
System.out.println("Conexión exitosa");
}catch(Exception e){
System.out.println("Error al intentar conectarse a la base de datos: "+e);
}
return Conector; //Se retorna la conexión
}
}
---------------------------------------------------------------------------------------------------------------
Clase Usuario (importar las clases necesarias):
public class Usuario{
/*Para realizar la conexión a la base de datos hay que llamar la función Conectar()
que forma parte de la clase Conexión. Para poderla llamar hay que crear un
objeto de esa clase (a esto se le llama instanciar). Una instancia de clase u objeto
de clase es una puerta de acceso a otra clase, esto quiere decir que cualquier
objeto de una clase puede tener acceso a los métodos y atributos de dicha clase.
En este caso necesitamos tener acceso a la función Conectar(). Para crear la
instancia hacemos lo siguiente:
*/
private Conexion Obj_Conexion; //Se declara un objeto conexión.
private Connection Conector; //Se declara un conector propio para esta clase que almacenará la conexión que nos devuelve la función conectar().
Statement Ejecutador; //Se declara el objeto que se encargará de ejecutar las sentencias SQL
//Se inicializan las variables anteriores dentro del constructor de la clase:
public Usuario{
Obj_Conexion = new Conexion(); //Se crea el objeto de la clase Conexion mediante la palabra reservada 'new'.
Conector = Obj_Conexion.Conectar(); //Se almacena la conexión que devuelve la función Conectar() la cual se llama mediante el objeto de la clase Conexion
Ejecutador = Conector.createStatement(); //Se crea el ejecutador de sentencias usando la conexión a la base de datos.
}
//En teoría, la conexión esta lista. Ahora hay que usarla para poder registrar, modificar, eliminar o consultar usuarios, por ahora hagamos solo el registro:
//Campos necesarios para registrar un usuario:
private String Usuario;
private String Contraseña;
//Métodos 'setter' para asignarle valores a las variables anteriores:
public void setUsuario(String Usuario){
this.Usuario = Usuario;
}
public void String setContraseña(String Contraseña){
this.Contraseña = Contraseña;
}
//Función para registrar al usuario (true si registra, false de lo contrario):
public boolean Registrar(){
String Sentencia_SQL = "INSERT INTO Usuarios VALUES ("+Usuario+", "+Contraseña+")";
try{
//Se ejecuta la sentencia de arriba:
if(Ejecutador.executeUpdate(Sentencia_SQL) > 0){
return true; //Si se registra el usuario correctamente en la base de datos: la función retornará verdadero
}
}catch(Exception e){
System.out.println("Error al intentar registrar al usuario: "+e);
}
return false; //Si ocurre algún error se retorna falso.
}
}
Para la vista hagamos una clase de prueba que se llamará 'Login', para registrar usuarios.
public class Login{
public static void main(String args[]){
//Se instancia un objeto de la clase usuario para poder acceder a sus métodos y funciones:
Usuario Obj_Usuario = new Usuario();
Obj_Usuario.setUsuario("Mauro"); //Le mandamos el usuario que queremos registrar
Obj_Usuario.setContraseña("12345"); //Mandamos la contraseña
//Registramos y preguntamos si el registro fue exitoso:
if(Obj_Usuario.Registrar()){
System.out.println("Usuario registrado satisfactoriamente");
}
}
}
---------------------------------------------------------------------------------------------------------------
Recomendación:
Bueno, veo que estas hablando de conexión a base de datos y la existencia de diferentes clases que necesitan comunicarse entre sí. Aquí es donde entran los pilares de la programación orientada a objetos (Por lo menos la Herencia, el Polimorfismo y el Encapsulamiento).
Como estas manipulando varias clases y trabajando con conexión a base de datos (supongo que con el gestor MySQL), es recomendable usar patrones de diseño para hacer las cosas de una manera organizada y entendible.
Al principio comencé con MVC, no se si ya lo habrás usado o quizás hayas escuchado hablar sobre él, sin embargo te explico como funciona:
MVC son las siglas de Modelo, Vista y Controlador, es un patrón de diseño que se basa en la utilización de esas 3 capas para el desarrollo organizado de aplicaciones.
La vista es la primera capa: Es la interfaz final con la cual los usuarios interactúan.
El controlador es la segunda capa: Es el que se encarga de recibir las peticiones que se envían desde la vista hacia el modelo y, de la misma manera, recibe la respuesta de esas peticiones de parte del modelo para enviarla devuelta a la vista.
Por último se encuentra el modelo: Es quien se encarga de hacer las operaciones que se requieran para cumplir con una petición e la vista. Cuando se cumple dicha petición, el modelo le envía al controlador la respuesta adecuada.
Ahora, en tu caso, identifiquemos que parte hace cada quién:
La vista será la interfaz de usuario: La ventana de inicio de sesión y la ventana principal.
El controlador será una clase que se encargará de recibir las peticiones de la vista y enviarlas al modelo: En este caso, por ejemplo, cuando el usuario quiere iniciar sesión, ingresa los datos correspondientes y pulsa el botón ingresar, al dar click en ese botón, la vista recogerá esos datos y se los enviará al controlador, este los recibirá y se los enviará al modelo.
El modelo será el contacto directo con la base de datos: Es aquí donde deberás crear la clase de la conexión a la base de datos y las otras clases que usarán esa conexión para operar con la base de datos. Te recomiendo crear una clase por cada tabla que tengas en la base de datos. En estas clases se almacenarán los métodos que se encargarán de ejecutar las sentencias SQL (el CRUD: Insert, Update, Delete y Select).
Retomando el ejemplo anterior, cuando el controlador le mande al modelo los datos del usuario que desea ingresar, el modelo se conectará a la base de datos y comprobará si el usuario existe o no. Si existe, le responderá al controlador diciéndole que es un usuario válido, sino, lo contrario. Por ultimo, el controlador le retornará esa respuesta a la vista y la vista decidirá si dejarlo ingresar al sistema o mostrarle un mensaje de error.
Nota: En la práctica, Modelo, Vista y Controlador respectivamente hacen referencia a paquetes de java que deben ser creados para contener las clases correspondientes, es decir, en el paquete 'Vista' se encuentran las interfaces de usuario, en 'Controlador' los controladores (uno por cada clase del modelo, excepto la de Conexión a base de datos) y en 'Modelo' las clases que interactúan con la base de datos.
Es muy interesante trabajar de esta manera, la principal ventaja de usar patrones de diseño es que las aplicaciones (Especialmente las que son un poco mas grandes) son más fáciles de gestionar y mantener, además te permiten llevar un control sobre lo que estás haciendo y cómo lo estás haciendo, previniendo futuras fallas, que si en algún momento llegan a haber, vas a saber mucho más fácil en donde se encuentran y como corregirlas sin afectar el desempeño de las otras clases. En Internet puedes encontrar mil y un tutoriales sobre como implementarlo, el aprendizaje depende directamente de ti.
Saludos.
Hola de nuevo, muy buena explicación mauro, solo una cosita... según tu tienes la clase conexión, no la veo optima, porque cada vez que llamas al metodo conectar, estas creando una conexión nueva, cuando hagas 8 operaciones diferentes, te quedaran 8 conexiones abiertas a la bbdd, es recomendable usar el patrón singleton(Asegurarte que solo hay una instancia del objeto connection en cada momento....) para la clase conexión, o cerrar las conexiones tras acabar cada operación. Si no pueden quedar conexiones abiertas, y llegar un momento en que mysql nno te permita hacer mas ;).
Bueno un saludo!!
Muchas gracias, en cuanto tenga un momento lo probaré y ya os comento.
Tienes toda la razón Loderain, incluso pensé incluir el patrón Singleton al momento de postear dicha solución, sin embargo no lo hice porque consideré que era algo un poco mas avanzado y me gustaría que las personas lo hubiesen investigando por su cuenta para que supieran la gran utilidad que tiene ese patrón de diseño.
Como solución podríamos crear un método dentro de la clase Conexión que se encargue de cerrarla.
Podría ser así:
public void Desconectar(){
try{
if(Conector != null){
Conector.close();
}
}catch(Exception ex){
System.out.println("Error al intentar cerrar la conexión con la base de datos: "+ex);
}
}
De igual manera podríamos implementar el patrón Singleton para evitar crear más de una instancia de la clase Conexion y por ende, mas Conexiones a la base de datos (No querrás encontrarte con el error "Too many connections"). Se podrían hacer las siguientes modificaciones dentro de la clase Conexion:
//1. Declaramos un único objeto dentro la misma clase:
private static Conexion Obj_Conexion;
//2. Declaramos el constructor privado para evitar crear objetos de esta clase desde otras clases:
private Conexion(){
//Codigo del post anterior
}
//3. Creamos una función pública que devuelva la instancia del objeto que hemos declarado anteriormente:
public static Conexion getInstance(){
//Si aun no se ha instanciado el objeto, se realiza la instancia y luego se retorna (Esto solo se ejecuta la primera vez que se llame la función):
if(Conexion == null){
Obj_Conexion = new Conexion();
}
return Obj_Conexion;
}
//4. Para llamar la instancia desde cualquier clase aparte simplemente hay que llamar la función que hemos creado anteriormente de la siguiente manera:
private static Conexion Obj_Conexion = Conexion.getInstance();
//Ahora el Obj_Conexion local de esta clase contiene el mismo objeto que se creo en la clase Conexion.
Gracias a Loderain por las sugerencias, espero haber ayudado y resuelto las falencias de mi código anterior, saludos a todos
Guenas.
El usar una única conexión no lo considero obligatorio. Se pueden usar varias dependiendo del objetivo.
Si usas una única conexión, en muchas BD también tendrás una única transacción. Muchas veces te interesara tener mas de una transacción independiente en curso. Mira el objetivo, características de la BD y tiempos y despues decide.
Un saludo,
Paposo
Hola,
Soy novato y estoy comenzando a programar en java y he realizado un programa que en una misma clase realiza la conexion a la base de datos e interactua en ella, hasta aquí ningun problema.
Ahora lo que quiero es realizar ese mismo programa de forma que la aplicacion tenga varias ventanas (clases), en la ventana principal se identificara para poder conectarse a la base de datos (hasta aquí tambien ok).
Y en las ventanas secundarias (otras clases que estaran incluso en otros package) puedan interactuar con la base de datos ¿Como podría hacer eso?
Gracias de antemano.