Estou trabalhando em uma agenda de marcações. Diversas pessoas abrem ao mesmo tempo a agenda para verificar se tem horário disponível. Se não estiver com o indicador “ocupado”, elas clicam no horário e o horário é reservado para elas.
O problema é que algumas pessoas estão conseguindo marcar o mesmo horário (com diferenças pequenas, de segundos entre as marcações). A parte de apresentação é toda em jsf e o código que controla a aplicação está em um EJB que é importado como biblioteca para a aplicação.
Existe alguma forma de conseguir impedir que as pessoas marquem o mesmo horário, de preferencia, sem ser por multithread?
Sugiro que você crie um método sincronizado para marcar o horário. Antes de marcar o horário verifique se já não está marcado. Caso esteja, mostre uma mensagem informando que não foi possível marcar o horário, pois esse está sendo utilizado por outra pessoa.
Também gosto de fazer esse tipo de restrição no banco de dados. Não sei como você modelou, mas seria interessante ter uma tabela com as marcações onde o campo do horário tenha a restrição única (unique).
O
option
Essa verificação já é feita.
O problema é que enquanto está retornando a resposta do banco para a aplicação, alguém já foi lá e fez a inserção. Tenho diferença entre as marcações de 2 segundos.
Não fui eu quem modelou a tabela, vou verificar se existe a restrição unique para o timestamp de horário =)
rafaelsantini
Mas se o método da inserção for sincronizado, outro usuário não conseguirá marcar o mesmo horário.
felipeguerra
11.3. Optimistic concurrency control
The only approach that is consistent with high concurrency and high scalability, is optimistic concurrency control with versioning. Version checking uses version numbers, or timestamps, to detect conflicting updates and to prevent lost updates. Hibernate provides three possible approaches to writing application code that uses optimistic concurrency. The use cases we discuss are in the context of long conversations, but version checking also has the benefit of preventing lost updates in single database transactions.
11.3.1. Application version checking
In an implementation without much help from Hibernate, each interaction with the database occurs in a new Session and the developer is responsible for reloading all persistent instances from the database before manipulating them. The application is forced to carry out its own version checking to ensure conversation transaction isolation. This approach is the least efficient in terms of database access. It is the approach most similar to entity EJBs.
If you are operating in a low-data-concurrency environment, and do not require version checking, you can use this approach and skip the version check. In this case, last commit wins is the default strategy for long conversations. Be aware that this might confuse the users of the application, as they might experience lost updates without error messages or a chance to merge conflicting changes.
Manual version checking is only feasible in trivial circumstances and not practical for most applications. Often not only single instances, but complete graphs of modified objects, have to be checked. Hibernate offers automatic version checking with either an extended Session or detached instances as the design paradigm.
Muito obrigada pelas respostas. Vou testar aqui e retorno o resultado =D
viniciuspadua
Ao clicar no botão para nova inserção verifique se existe vaga disponível
1.1. Caso exista
a) Insira um novo registro vazio e relacione apenas com o horário. Servira para se alguém clicar no btn (passo 1) a verificação falhar.
b) Redirecionar para a tela do usuário preencher os dados
c) Atualizar o registro incluído (passo a) com o dados informados (passo b)
1.2. Caso não exista
a) Avise ao usuário
O
option
Vinicius, obrigada pela sugestão, mas o usuário não preenche nada. Ele só tem que clicar em um horário =)
Felipe, sinceramente, não sei como implementar a sua sugestão, pois o método responsável pela marcação está num EJB e ele não cuida de sessão.
É correto colocar esse controle de sessão no EJB??
Quanto a tentativa que fiz, citada acima, esqueci de falar o erro que retorna.