| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java EE (J2EE) и Spring > Двойное нажатие кнопки Submit |
| Автор: Zamuta 28.11.2006, 17:45 |
| Всем привет. Моё приложение регистрирует пользователей, заносит полученные данные в таблицу, а затем работает с этими данными из таблицы. Приходилось ли кому-нибудь сталкиваться с проблемой двойного нажатия кнопки отправки данных? Ведь если нажать кнопку дважды, то получатся две одинаковые записи в таблице. Есть ли готовые решения в NetBeans или Eclips'e или где-нибудь ещё? На сколько критично стоит относиться к этому вопросу? |
| Автор: Zamuta 28.11.2006, 18:18 |
| А если получится так, что у юзера медленный инет. Он нажимает кнопку отправки данных, код проверяет есть ли такие же записи в бд, видит что нет и сохраняет данные, на всё это уходит некоторое время, а юзер после первого нажатия тут же нажал второй раз, ну нервный юзер, например, началась проверка на такие же записи в бд, логин, например, а первые данные ещё не сохранились и получается, что такого логина ещё нет и приложение ставит эти данные в очередь на запись в бд. Т.е. проверка прошла успешно, а данные записались дважды. Что тогда? У меня на локалхосте так и получается, но это без проверки совпадения на уже существующие данные.... Это мои соображения, сомневаюсь, поэтому спрашиваю...... |
| Автор: Sherst 28.11.2006, 18:29 |
| Что мешает сделать поле уникальным и ловить exception? |
| Автор: chief39 28.11.2006, 18:33 | ||
| База данных должна поддерживать транзакционность и некторорые уровни изоляции на которые следует обратить внимание ;) Поэтому если ты в одной транзакции будешь проверять есть ли запись и вставлять - вторая вставка просто не пройдёт.
Логично А если хотя бы поставить уникальный индекс на необходимую совокупность полей -СУБД сама не допустит такого, но будет ругаться некрасиво - лучше самому сделать проверку. А выносить контроль целостности данных на клиентскую часть - не очень хорошо... :-/ Можно дополнить и продублировать, но это уже так.. фича, необходимая в определённых случаях |
| Автор: Sherst 28.11.2006, 18:33 |
| Можно еще как-то попробовать сообщать юзеру что идет процесс записи данных... Например сделать кнопку Добавить невидимой после окончания записи - показать. |
| Автор: chief39 28.11.2006, 18:47 | ||
Но это, опять-таки, лучше делать дополнительной фичей. Если важна целостность данных, а не красота(а как ещё может быть) - то надёжнее, вернее и правильнее делать это ближе к данным. Поскольку никто не мешает открыть ещё один браузер на другой машине. И уж ему-то точно будет плевать с высокой горы на видимость/невидимость/цвет/форму кнопки соседа |
| Автор: Sherst 28.11.2006, 18:49 |
| У SQLException юзай метод getErrorCode() Добавлено @ 18:50 chief39 согласен |
| Автор: Zamuta 28.11.2006, 21:34 | ||
| Спасибо всем за ответы.... Вообще, проверку на совпадение логинов нужно сделать, ведь нужно както-же юзеров различать.... А для предотвращения двойного нажатия кнопки мне больше понравилась идея Sherst
Как такое можно сделать? У меня в NetBeans я вижу такие параметры для кнопки как disabled и immediate. Это не то случайно что нужно? Как Вы считаете? |
| Автор: Sherst 29.11.2006, 01:34 |
| Zamuta для начала скажите какой web-фрейморк используете: JSF, struts и т.д. А дальше будем думать что можно сделать ... |
| Автор: chief39 29.11.2006, 11:45 | ||||||
Не понял... проверку уникальности логинов при создании? Или что?
Тебе нужна функциональность или опыт работы с кнопками?
Насколько помню, в джаваскрипте можно устанавливать кнопке свойство в true - кнопка задизаблится. У меня вознил один вопрос(для начала) - это курсовая для преподавателя(самостоятельные разборки с технологиями) или коммерческое/промышленное приложение? Если второе - тогда порекомендую пересмотреть подход BTD(button driven development) и начать с продумывания архитектуры. Принцип "нарисовать кнопку, а потом придумать что она будет вызывать" может натворить много бед |
| Автор: Zamuta 29.11.2006, 14:03 | ||||||||
Sherst,
Использую JSF. chief39,
Да. Т.е. перед каждой записью делать проверку. Если запись есть - то вторую не добавлять.
Мне нужна функциональность. Но существуют такие решения, как шаблоны проектирования, т.е. готовые решения, скажем валидаторы или конвертеры, если не ошибаюсь. Так вот, чтобы не изобретать велосипед, возможно уже есть методы решения этой проблемы, т.к. до меня, думаю, люди с этим сталкивались.
Это коммерческое/промышленное приложение. Дело в том, что у меня двух одинаковых записей быть не должно, это критично.... Примерно понял, делаем поле для сохранения логина в бд уникальным и используем getErrorCode() у SQLException, таким образом решаем сразу две проблемы, т.е. сохраняем все логины уникальными, и предотвращаем многократное нажатие кнопки..... Всем спасибо за ответы.... |
| Автор: Sherst 29.11.2006, 14:50 | ||
БД сама все проверит лишь бы уникальное поле было Для jsf компонент можно использовать свойства rendered - видно/скрыто, disabled - доступно / недоступно Но в коммерческом приложении это будет лишним, а Exception можно всегда обработать. Я обычно делаю страничку Error и при возникновении exception направляю юзера на эту страничку на которой вывожу также текст ошибки . |
| Автор: alexsmirnov 29.11.2006, 15:10 |
| Ловля Exception и проверка уникальности в базе не поможет - после первого нажатия пользователь занес свои данные. По второму возникла ошибка - и в результате юзер видит что зарегистрироваться он не смог, хотя все в порядке. Лучше либо действительно сразу на странице запрещать кнопку через JavaScript, либо ставить в форму скрытое поле с уникальным id и проверять повтор. |
| Автор: Zamuta 29.11.2006, 15:44 |
| Кажется нашёл. Какой способ предпочли бы Вы? 1) http://www.javable.com/javaworld/tips/136_tt/ 2) http://www.netmechanic.com/news/vol5/html_no16.htm |
| Автор: y3u 30.11.2006, 00:45 |
| стандартный, принятый повсеместно способ, после нажатия на submit кнопка просто тупо дизейблится прямо сразу, и все... после того как форма отправится на сервак, страничка все равно перезагрузится, т.е. кнопка без доролнительных телодвижений будет раздизейблена... |
| Автор: chief39 30.11.2006, 15:49 | ||||||
| Предисловие: - они сделают только косметические дейсвия без завязки на огромный запас данных, которые в БД. А мы говорим как раз о данных...
Фффух... ну тогда я просто не понимаю упорного тяготения к красоте скрытия кнопочки..... Задизабленная кнопка решает только двойной клик на машине, клик на соседней машине она не решит в принципе.
Это весьма полезно и стоит это применить(способ действительно полезный и проверенный). Но это скорее доп. защита от шаловливых ручек ("НУ НЕ ТЫКАЙ ТЫ ТУДА! - ВИДИШЬ? - ГРУЗИТСЯ!!! СИДИ ЖДИ!!"). Напишу ещё. Но если это промышленное приложение и у него есть критичные условия(что естественно) - тогда стоит поглядеть на него не со стороны браузера, а со стороны функциональности и логики работы. Гораздо важнее чтобы Пользователь не обнаружил Своего двойника в один прекрасный момент чем красота и чуть ли анимация при создании себя любимого в базе. Машины тоже отличаются цветом и фомой шильдиков. Но сначала проектируется ходовая, движок, трансмиссия, несущие и аэтодинамические характеристики кузова, и только потом уже приделываются ручки, зеркальца. Ярко выделяются два направления(не учитывая остальных): Те, кто пересел с ПХП на джаву как инструмент написания вэб-движков. И мыслит категориями динамических страничек. Как правило, первый путь: хэлло-ворд -> сервлет хелловорд. Далее идёт спуск в глубь джавы "ух ты... так тут ещё и не только странички...". И те, кто пересел с сипипи и близких к нему. Тут человек поглядывает немного искоса на вэб и пишет десятки програмулек, радуется как ребёнок обилию коллекций, полезных библиотечек и пакетиков , а потом с подозрением встречает развесёлую компанию сервлетов и джсп. Потом различия нивелируются, многие идут совершенно своим путём, но моя подсознательная имха такова. Кажется, автор принадлежит первой школе. Это не в обиду, везде свои плюсы и минусы. Просто отталкиваясь от этого буду говорить. Вобщем, поехали: У нас есть несколько уровней где мы можем противостоять хаосу:
Главное - попросить её приглядеть за данными, создав уникальный констрэйнт Итак, это - нужно Но тут сидит ещё один нюанс... чтобы работать, опираясь только на один констрэйнт - надо отлавливать ошибку и обрабатывать её сверху как обсуждалось выше... Нюансов становится два:
Перед тем как ломиться в дверь - давайте проверять - а есть ли дверь? Нет двери - сообщите корректным нормальным сообщением юзеру что "двери нет", "пива нет", "туалет занят", "Маня вышла" etc. Зачем кричать что-то похожее на kernel panic?? Пусть внемлет ситуации и войдёт в другую дверь(выпьет водочки, пойдёт к Тане). Тут логика не страдает - мы просто переносим наши логичные поступки из реального мира в мир абстракций и цифр. 3) Поднимаясь к самой верхушке айсберга.... Дизаблить кнопочку... вроде бы и не надо уже... но почему же не надо? Надо! Главное не перепутать тёплое с мягким. Дизабл спасёт от нескольких вещей. Во-первых, не позволит человеку по глупости/спешке исскуственно создавать глупые ситуации: Три раза кликнул - три раза попросил создать юзера(а нафея тебе столько? - спросит добрая фея). Пресечём такую попытку ещё в зародыше. Во-вторых, такая вещица полезна при неких сложных сессионных работах. Создали мы временную запись в одной таблице, во второй, в третьей, что-то сложное посчитали на их основе, добавили ещё одну - а вот тут уже два раза клацать не надо!!! Может человек добавляет платежи, и добавить платёж с суммой 20 он может хоть сто раз. Но клиент заплатил всего 20. Поэтому, пощёлкав по кнопке, он надобавляет 80, 120, 240 на счёт клиенту. Даже не подозревая ни о чём(Я просто разместил объяву!!! - ну, то есть, просто давил на кнопку!!! Итого, теперь я бы внимательно подумал... В том числе и над фразой
(Как-то, вроде-бы, неплохо бы...) И всё-таки начал бы с тщательного проектирования организации данных, потом полной структуры базы данных, потом бизнес-ограничений и процессов, и уж потом - реализация, тем более, интерфейса. Вот такая здоровая вышла оффтопина.... |
| Автор: Zamuta 10.12.2006, 01:34 | ||||||
| Привет всем. Сделал поле для хранения имени пользователя в бд уникальным. Ну и само собой теперь вылетает ошибка при попытке записать такое же значение.
И теперь, при попытке создания
Пишет, что exception java.sql.sqlexception has already been caught, но до этого места я нигде больше не ловлю sqlexception. Смысл в том, чтобы при появлении значения в SQLException ex выводилась ошибка о существовании уже существующей записи. И кстати везде обыскал, но у SQLException метода getErrorCode() так и не нашёл, как сказал Sherst |
| Автор: batigoal 10.12.2006, 11:49 | ||
Хм. http://java.sun.com/j2se/1.4.2/docs/api/java/sql/SQLException.html#getErrorCode() Должон быть. Я немного не понял твой вопрос. Ты в коде делаешь обработку ЛЮБОГО исключения (catch(Exception e)). Поэтому, разумеется, SQLException в твоем коде уже никогда не будет выброшен наружу. Убери try/catch, и тогда в случае ошибки SQLException будет выброшен из saveToDatabase(). |
| Автор: Sherst 11.12.2006, 01:59 | ||
|
| Автор: Zamuta 11.12.2006, 22:39 | ||||||
| Sherst, По определению public int getErrorCode() это int тип, поэтому я не могу сравнить его значение с логическим значением и сделать
Но так как errorCode возвращает the vendor's error code, то думаю, что его можно сравнить с нулём вот так
Так всё ловит, но это не есть гуд. Суть такова, что на странице регистрации сообщения об ошибке ввода данных выводятся на этой же странице, но только не сообщение о дублировании имени, т.к. приложение об этом узнает только когда попытается записать данные в бд. Сейчас сообщение "Nickname already exist" выводится на странице о неудачной записи данных, т.е. после попытки записи в бд, а мне нужно чтобы небыло перехода на другую страницу. Как сделать с переходом на другую страницу я само собой уже понял.
|
| Автор: Sherst 12.12.2006, 01:02 | ||
Зачем ? Смоделируй ситуацию когда происходит добавление 2-ух идентичных записей и посмотри чему равно значение errorCode. А дальше используй это значение для определения того что у тебя произошла ошибка связанная с дублированием записи. Дальше, как я понял, есть общая страница ошибок, но ты хочешь что бы в случае неправильной регистрации не было перехода на эту страницу, а все выводилось на странице регистрации или я не правильно понял? |
| Автор: Zamuta 12.12.2006, 01:30 | ||||
Согласен, щас попробую.
Да, ты правильно понял. У меня так и работает проверка корректного ввода данных имени, майла, пароля и проверки повтора ввода пароля (см. выше validate() ). Хотелось бы и на совпадение имён сделать вывод ошибки здесь же. Но логику пока так и не продумал. Т.е нужно подключиться к бд не перезагружая страницу и вывести на ней ошибку. |
| Автор: Sherst 12.12.2006, 12:38 | ||||||||||
Что бы что-то вывести нужно эту страницу перегрузить иначе ничего не получится. Как бы сделал я метод класса по работе с БД:
Далее класс контроллер (UserHandler.java): В нем делаешь переменную которая будет содержать текст ошибки: String errorDescription, пишешь get set методы для нее. Метод нажатия на кнопку:
Оформляем faces-config.xml
Все это выводишь на jsp страничке. Описание ошибки будет такое
|
| Автор: Wowa 26.2.2007, 15:54 |
| В ПХП эта проблема решается ОЧЕНЬ легко. После вставки данных в базу нужно лишь послать заголовок браузеру о переадресации. Делается это так: header("Location: http://site.com/thanks.html"); Этот метод работает просто замечательно. Разве нельзя нечто подобное на Java сделать?? Ведь нужно: 1. Послать заголовок 2. Отобразить след. страницу |