style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Problema Existencial con java y JDBC para mysql

Buenas, no se si lo que les comentare es un simple rollo existencial, o quizas aun le sucede a muchos programadore cuando iniciamos una aplicacion con acceso a bd.

Actualmente complete una aplicacion, la cual distribuyo en un jar, el mismo se ejecuta independientemente en cada maquina en la que se monte, esta aplicacion se conecta a una maquina la cual hace de servidor para MySql, mis tablas estan definas bajo una estructura de innoDb, mi aplicacion possee una clase connection que contiene los metodos para consulta, actualizaciones y delete de registros., estos metodos son accedido desde la clase que lo invoque.

Actualmente mi aplicacion funciona a la perfeccion, pero actualmente la necesidad requiere que cambie mi modelo de conexion para que pueda trabajar con multiples usuarios, intente implementar un pool de conexiones, pero no soluciona mi necesidad, ya que con mi actual modelo de conexion, yo abro y cierro mi conexion acorde lo que vaya realizando, es decir, nunca la dejo abierta., cuando se requiere hacer alguna operacion, la abro y luego la cierro.

Con el pool de conexiones, mi conexion esta abierta todo el tiempo, y lo que hace es instanciar un nuevo hilo y no es lo que deseo.

Mi problema es la concurrencia... como puedo hacer, para cuando consulto un registro, este se bloquee para otros usuarios para operaciones a nivel de update y delete, no quiero bloquear la tabla., simplemente quiero implementar en mi modelo de conexion un metodo que indique al usuario que el registro seleccionado esta a modo de consulta.,

mi modelo de conexion es el siguiente.

import java.sql.*;
public class CS_Conexion {
       
        public String driver,url,ip,bd,usr,pass;
        public Connection conexion;
        private Statement stm;
       
public  CS_Conexion (int status,String db){
       
                       
                        ip="xxxxxxxxxxxxxxxxxx";                       
                        bd=db;
                        usr="xxxx";
                        pass="xxxx";
                        url = new String("jdbc:mysql://"+ip+"/"+bd);
                        driver="com.mysql.jdbc.Driver";
                                if (status==1){
                               
                                        try{
                                                Class.forName(driver).newInstance();
                                                conexion=DriverManager.getConnection(url,usr,pass);
                                                stm=conexion.createStatement();
                                        }catch (Exception exc){
                                        System.out.println("Error al tratar de abrir la base de Datos" +"  "+bd+ " : "+exc);
                                        }
                                }
        }
               
public Connection getConexion(){
        return conexion;
}

private Statement getStatement(){
        return this.stm;
        }

public ResultSet dbSelect(String sentencia){   
        ResultSet rs = null;
        try {
               
                rs = this.getStatement().executeQuery(sentencia);
               
        } catch (SQLException ex) {
                System.out.println(ex);
        }
return rs;
        }

public boolean dbOperaciones(String sentencia){
        boolean rs = false;
       
        try {
                rs = this.getStatement().execute(sentencia);
                } catch (SQLException ex) {
                        System.out.println("El Registro actual no puede ser actualizado");
                }
        return rs;
        }

public int numFilas(String sentencia){
        ResultSet rs = null;
        int numero = 0;
                try {
                        rs = this.getStatement().executeQuery(sentencia);
                        while(rs.next()){
                                numero++;
                        }
                        rs.close();
                                } catch (SQLException ex) {
                                        System.out.println(ex);
                                }
                return numero;
        }

public Connection CerrarConexion() throws SQLException{
       
        conexion.close();
        conexion = null;
        return conexion;
       
 }

}
<code/>

Pense que la solucion podria ser al crear el objecto Statement (stm=conexion.createStatement(Indicar aqui si es lectura); pero de igual forma no me funciona.... he buscado por internet, ejemplos y mucho mas, pero todos hablan de las 20 mil maneras para crear una conexion, hablan de las transacciones, pero nadie aplica en sus modelo de conexion los metodos para controlar la concurrencia... Si pudieran iluminarme un poco se los agradeceria.

Gracias.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Has intentado con synchronized ?

Este dilema no se presenta sólo con mysql, aunque imagino que esto ya lo sabes, lo digo por el título de tu post.

Has intentado usar la palabra reservada synchronized de java?

Con dicha palabra colocada en la declaración de tu método bloqueas a que un sólo proceso o hilo a la vez acceda a tu método.

public synchronized void miMetodo(){}

Aunque el hecho de sincronizar un método obviamente bajará un poco el rendimiento de éste, ya que si otro hilo trata de acceder, se tiene que esperar a que el proceso o hilo que lo tiene lo desocupe.

Acá tienes un poco más de información al respecto.

http://www.sc.ehu.es/sbweb/fisica/cursoJava/applets/threads/sincronizaci...

Salu2

Has intentado con synchronized ?

En este caso, ya habia intentado esa solucion, pero implicaria que al momento de sincronizar el metodo afectaria a todo aque que intente usar el mismo metodo para diferente registro, es decir., si yo realizo una consulta a la tabla A el metodo se sincroniza y mi hijo esta en ejecucion, otra persona desea consultar la tabla b no puede, porque hasta quemi hilo no se destruya el metodo no puede ser ejecutado., bajo esa condicion no solventa mi problema.,

Creo que tendre que cambiar la logica, a un modelo de pool de conexiones en la cual la conexion este abierta all time, cuando un usuario haga una solicitud el pool le asigne un hilo nuevo ó recicle uno liberado, y como la conexion esta abierta el registro puede ser bloqueado por el proceso por medio del metodo readOnly cuando se crea el statement y se libera cuando el usuario devuelve la conexion... de resto no conozco otra forma en la que pueda lograr lo que deseo con mi actual modelo de conexion.,

Pero la otra pregunta seria, debo incluir mi modelo de pool de conexiones en cada jar que distribuya? o debo incluir una clase tipo socket que se distribuya con cada jar que monte por equipo y esta clase socket se comunica con mi clase poolconection que en teoria debiera estar en el servidor?

como seria la metodologia mas limpia para esta implementacion?

Imagen de ezamudio

FOR UPDATE

dentro de una transacción, obtienes el registro que quieres afectar con FOR UPDATE y se bloquea. Pero no vayas a hacer eso cuando empiezan a editar el registro porque luego el usuario se larga a tragar y te deja el registro bloqueado horas. Eso debe ser solamente para evitar problemas de concurrencia en los commits. Mejor lee acerca de estrategias de bloqueo optimistas y pesimistas (pessimistic locking, optimistic locking).

(pessimistic locking, optimistic locking).

Gracias ezamudio, ahora eso me permitiria solucionar mi problema, tomendo en consideracion, que cada maquina ejecutar un jar de la aplicacion y dentro de ese jar esta la clase conexion que describi antes, y que cada usuario cuando requiere consultar o realizar una transaccion, abre la conexion y luego la cierra, es decir.. nunca tengo una conexion abierta, ya que.. la base de datos esta en una maquina remota y es la encargada del servidor mysql, y cada jar (cada maquina) se conecta a la base de datos.. no es una aplicacion centralizada por definirla de una manera.

Imagen de ezamudio

eh

No entendí si estás afirmando o preguntando. En caso que estés preguntando si las estrategias de locking funcionan con aplicaciones distribuidas, la respuesta es sí, porque se aplican en la base de datos, no se hacen en la aplicación (la aplicación tiene implementado el código etc pero el candado en tiempo de ejecución, o los mecanismos para detectar modificaciones posteriores, se hacen en la base de datos central).

Imagen de beto.bateria

Investiga acerca de los

Investiga acerca de los contextos, aqui un ejemplo de como se declaran:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/empenio" docBase="empenio">
        <Resource
                name="jdbc/mysql"
                auth="Container"
                type="javax.sql.DataSource"
                username="juan"
                password="perez"
                driverClassName="com.mysql.jdbc.Driver"
                url="jdbc:mysql://127.0.0.1:3306/classicmodels?autoReconnect=true"
                maxActive="8"
                maxIdle="4"
        />
</Context>
<code>

¿Y si cambias tu Conexión a un server de aplicación?

En tu segundo post comentaste

------------------------------------------------------
Pero la otra pregunta seria, debo incluir mi modelo de pool de conexiones en cada jar que distribuya? o debo incluir una clase tipo socket que se distribuya con cada jar que monte por equipo y esta clase socket se comunica con mi clase poolconection que en teoria debiera estar en el servidor?
------------------------------------------------------

Es decir, que si puedes hacerlo, hazlo!, cambia tu administración de conexiones del lado del server, no se que tan complicado te sea cambiar lo que ya tienes pero te evitarías todos los problemas que estás teniendo.

Ahora que para esto, tendrías que usar un servicio montado en un server de aplicación el cual atienda todas las peticiones de consultas, altas, bajas, modificaciones hacia tu B.D. Depende de como tengas organizado tu ambiente, pero idealmente el server de aplicación tendría que estar en otra máquina para que no se sature la memoria del server de B.D.

Esto es sólo una opción, puedes usar lo que te han sugerido los otros compañeros.

Imagen de beto.bateria

¿Estas hablando de una

¿Estas hablando de una aplicacion swing? si es asi, creo que lo que debes de configurar es la base de datos. Al menos en Oracle habia 2 o 3 formas de configurar el acceso a la base de datos.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">