Única Instância de uma classe

Boa tarde pessoal.

Estou terminando de desenvolver um programa para controle de estoque.
Vou sábado agora no cliente implantar.
Entretanto, me deparei com um problema seríssimo que pensei já tivesse resolvido.

Vamos lá, vou tentar me fazer entender…

Dentro do programa, eu tenho uma classe chamada BD, que irá fazer todas as consultas, inserts e updates no banco de dados. Apliquei nesta classe o padrão de projeto Singleton, como se segue:

private static BD instance = null;
    
    public static BD getInstance(){
        if(instance==null)
        {
            System.out.println("criando BD");
            instance = new BD();
        }
        return instance;
    }
    private BD()
    {
        try 
        {
            Class.forName(driver);
        } 
        catch (ClassNotFoundException ex)
        {
            System.out.println("Erro ao conectar ao banco: "+ex);
        }
    }

A Classe funciona sem problemas, e durante a execução do programa o Singleton funciona normalmente.
Entretanto fui fazer um teste clicando 2x no executável do programa (ou seja, abri 2x o mesmo programa, para simular 2 computadores executando o programa), e notei que ele cria uma instância da classe BD pra cada instância do programa propriamente dita.
Então resolvi aplicar o Singleton para a classe Main, que gera o programa, e não resolveu, ou seja, ele cria uma instância do programa para cada vez que executo o jar.

O que preciso: que o programa sendo executando em no máximo 3 computadores, compartilhe sempre a mesma instância da classe BD para manipulação do banco de dados, pois com isso eu garantirei que o banco não será manipulado simultaneamente gerando incontáveis problemas…
Todos podem imaginar o problemão de dois computadores estarem efetuando uma venda ao mesmo tempo se não houver esta restrição…o pior deles é duas vendas como mesmo número, o que não poderá acontecer, jah que a tabela de venda tem o número da venda como primary key, que por sua vez é uma foregin key de outra tabela…

Se alguém puder dar alguma luz ae pra mim, ficarei muuuuuuuuuuuuuuito agradecido…

Vlw!!!

Se sua aplicação for desktop lógico que ele vai abrir 2 instâncias ou quantas vezes você abrir o programa uma solução seria você fazer um servidor e esse programa seu conectar nele, ai sim você terá uma única instância “servidor/cliente”;
Um exemplo pratico disso seria você fazer um sistema WEB.

Se você criar as transações corretamente, esses problemas que você está falando não existirão. O banco de dados somente executa uma transação por vez.

Uma alternativa técnica (aka gambiarra) é você serializar o objeto DAO e gravar ele (em um arquivo de texto, por exemplo) e criar uma fábrica dessa classe que verifica se o objeto está no tal arquivo, se já estiver, ele apenas recupera o objeto, senão, ele cria outor e salva (creio que deu pra entender)

se o programa for ser utilizado por mais de um computador, e não for uma app web, aí sim você iria precisar de uma gambiarra (POG nível 4 ou superior) pra procurar qualquer instância do programa e ver se tem o objeto criado e pegar o objeto via socket :shock: (não compensa)

[editando]
Me desviei completamente do foco do tópico, não faça isso…
[/editando]

O próprio banco de dados controla as transações por você, pesquise por níveis de isolamento :slight_smile:

(isso, entre outras coisas, que diferencia SGBD de planilhas do Excel)

Galera, muito obrigado pelas dicas…

A aplicação é desktop sim. E por alguns fatores relacionados ao cliente e o tipo de aplicação, não quis fazer um servidor para este programa.
Sobre a sugestão do drigo, realmente isso resolveria, mas quanto menos gambiarra eu colocar neste programa melhor, não quero muita dor de cabeça…rs

Sei que o banco tratará uma requisição por vez, mas o problema que eu vejo é o seguinte…

Quando eu vou fazer uma venda, preciso saber qual é o número da última venda, então faço a seguinte consulta:

 SELECT MAX(id) AS 'ID' from venda; 

Com isso eu tenho o valor da última venda. Guardo este valor no programa (não no banco) e procedo com minha tela de venda. Minha preocupação é, enquanto eu não fechar esta venda, se um outro usuário iniciar uma nova, ele vai pegar o mesmo valor de última venda que eu peguei, pois ainda não concluí a minha venda corrente… :? Fui muito confuso ?..rs

Eu já poderia no ato da consulta, gravar este número, mas esta tabela (venda) tem um relacionamento com outra tabela (venda_produto) pra eu poder fazer as normalizações que são necessárias…

Pelas dicas dos senhores, a única maneira que estou vendo de resolver isso, é assim que consulto o próximo número disponível, jah tenho que ter os produtos dessa venda assim como cliente, etc, e jah fazer tudo numa query só… certo?

Vlw pessoal!

Uma transacção != Uma query.
Para o teu problema, pesquisa por sequencias

Porque não gera o numero da venda após a venda ser realizada?
Assim você deixava o auto_increment rodar a vontade sem se preocupar com o número ocupado.

Como eu falei, você deve organizar direito as coisas no contexto de uma transação.

A maior parte dos bancos tem funções como a:

SELECT SCOPE_IDENTITY();

Do SQL Server, que retorna o último id gerado dentro daquela transação.

Além disso, em muitos bancos, uma transação não inicia até que outra seja concluída (ou assim ele faz parecer) e se a consulta ao MAX estiver dentro da transação, ela irá sempre retornar o valor correto.

Estude mais os recursos do seu SGBD. Não é por código Java que você vai resolver essa questão. Isso vale tanto para aplicações web, como para desktop.

Senhores, muito obrigado pela ajuda, e rapidez em que me responderam!!!

Já tenho um “norte” pra resolver este problema…

Como o ViniGodoy disse não será com Java que resolverei este problema… realmente… a questão toda está no como usar o SGBD.

ganondorfan, é isso que vou fazer!

Obrigado a todos!

Abraços!