Ну вот мы и добрались до конечной цели нашего ознакомления с технологией EJB. Несомненно мы не рассмотрели довольно много для этой технологии, но автор ставил себе цель ознакомить, дать некую ниточку, за которую вы сами сможете расскручивать эту технолгию.

 

Сделаю только одно замечание – для быстрого обновления изменений в коде я советую использовать правую кнопку мыши – кликаете наStudentsApp и выбираете пункт «Undeploy and Deploy»

 

Чтобы не откладывать в долгий ящки, начнем с текстов. После каждого файла я буду комментировать особо важные участки кода. И начнем мы с файлов, которые нам сгенерил NetBeans по структуре наших таблиц – Groups.java и Students.java

 

 

Groups.java

В данном файле все самое интересное находится в самом начале – это секция, где очень много надписей @NamedQuery. Вообще-то они генерятся в одну строку, но я для удобства восприятия разделил их на несколько. Это можно сделать без каких-либо проблем. Мы увидим некоторые их @NamedQuery чуть ниже. А пока важно уяснить следующее – это способ, который позволяет нам писать на EJB-QL.EJB-QL – это некоторый аналог SQL, только для EJB. Если внимательно посмотреть на значения строк query, то можно увидеть, что мы в какой-то мере обращаемся к объектам и их полям. Ведь на самом деле в таблице groups нет поля groupId. Там есть group_id. Но если посмотреть чуть ниже, то можно увидеть дополнительную аннотацию, которая «оборачивает» члены нашего класса. И это позволяет нам так красиво делать SELECT. Кроме того можно увидеть именованные параметры – они выделяются тем, что перед ними ставится двоеточие. Их хорошо должно быть видно.
Думаю, что поля, которые описаны возле @Column (name и nullable) достаточно очевидны. Также можно увидеть аннотацию @Id возле поля group_id. Прошу вас отметить, что это не элементарный тип данных int, а полноценный класс Integer. Т.е. он может быть равен null. Почему это важно мы увидим несколько позже. А пока запомните, что даже ID может быть NULL.

Students.java

Этот файл уже выглядит знакомым. Единственное, что мы в нем поменяли – это сделали несколько строк для именованных запросов (NamedQuery) и ДОБАВИЛИ свои – два последних — «Students.findByGroupAndYear» и «Students.updateGroupAndYear». Они нам просто понадобятся, потому и добавили.
Первый запрос отличатеся от стандартно сгенеренных тем, что он использует не один дополнительный параметр, а два. Второй запрос еще интереснее – он не возвращает данные, он изменяет их. Но в остальном ничем особым не выделяется.
Что еще хотелось бы отметить – все эти страшные аннотации интересны именно Application Server’у. Для тех, кто не использует их это самые обычные классы с обычными полями. Их можно скомпилировать и использовать где угодно. Но как только они попадают кAppServer’у, то у того сразу появляется информаци о том, к какой таблице «привязан» данный класс. И теперь как только происходит какая-либо работа с базой данных наш класс используется как хранилище для данных из строки таблицы. Т.е. если мы вытащим много записей из таблицы students, то все они лягут в список, элементами которого будут объекты класса Students. И это мы увидим прямо сейчас. Настало время обратить взор к одному из важнейших наших классов – ManagementSystemBean и его интерфейсуManagementSystemLocal.

ManagementSystemLocal.java

Здесь в общем-то ничего особенного нет – описаны необходимые нам методы. И интерфейс их содержит. Единственное, что вам рекомендуется сделать – это прочитать комментарии для чего каждый метод предназначен.
А вот реализация у нас займет несколько больше внимания и сил. Итак:

ManagementSystemBean.java

Вот здесь нам придется посмотреть на несколько методов.
getGroupsList() – этот метод получает список групп. Обратите внимание вот на что – здесь мы используем EJB-QL «напрямую». Т.е. создаем запрос и выполняем его. В остальных случаях используются именованные запросы.
getStudentsFromGroup(int groupIdint year) – здесь мы используем именованный запрос (который мы создали). В принципе каких-то сложностей в коде я не вижу – все достаточно очевидно.
moveStudentsToGroup(int groupIdint yearint newGroupIdint newYear) – в этом методе есть только один тонкий момент – здесь мы используем несколько другой вызов – executeUpdate. В других случаях мы использовали getResultList.
И вот тут мы подходим к методам, которые содержат некую хитринку.
insertStudents(Students st) – этот метод будет прекрасно работать только в одном случае. ЕСЛИ объект не имеет установленного поля studentsId. Помните я обращал ваше внимание на то, что теперь ID уже не элементарный тип, а реальный класс. Так вот – если он равен NULL, тогда будет производится его вставка в таблицу. Если же у него будет установлен ID – вставки не будет. Вернее будет, но только один раз. Это очень важный момент.
Когда я первый раз вставляю нового студента с установленным ID, то происходит следующее – PersistenceManager проверяет – нет ли студента с таким значением ID. Если нет – то он его вставляет. Если же такой ID был зарегистрирован, то данные студента пытаются обновить. Что очень важно – PersistenceManager не делает обновления ID при вставке у объекта, который мы вставляли. Что еще неприятнее – если вы вставили нового студента с установленным ID (ну так вышло), то если вы опять попытаетесь это сделать, то ничего не выйдет. PersistenceManager запоминает, что уже такой ID был, и он попытается проапдейтить студента. И тут мы обратим наш взор на метод updateStudents.
updateStudents(Students st) – посмотрите на код этого метода. В первой строке я должен вытащить студента по ID, изменить его поля на новые значения (которые я передал в аргументе) и снова сохранить. Т.е PersistenceManager должен иметь «привязанный» (attached) к базе объект. Я себе почему-то сразу представил, что мы «за резиночку» вытаскиваем структуру, заполняем ее, а потом отпускаем. ИPersistenceManager с уже новыми значениями притягивает «за резиночку» измененный объект и записывает его в базу. Может у вас появится другая ассоциация – но вот у меня такая получилась. А просто заполненный объект – он просто заполненный объект, который не имеет связи с базой и потому при попытке его сохранения вам будет выдано предупреждение. Попробуйте в методе закомментировать все строки и вставьте вот такую:

Посмотрите, что получится.
deleteStudents(int studentsId) – здесь та же самая иде «резиночки». Вытаскиваем «привязанный» объект и удаляем.

Файлы сервлетов я комментировать не буду – они просто очень похожи на те, что мы делали в Часть 9 — Простое WEB-приложение. Просто приведу текст. Не забудьте – они должны находится в проекте StudentsApp-war !

MainFrameServlet.java

StudetnFrameServlet.java

MainFrameForm.java

StudetnForm.java

Ну и JSP странички – вот такие.

 

MainFrame.jsp

 

 

 

StudentFrame.jsp

 

 

 

Также я привожу файл web.xml.

 

 

 

Обратите внимание на то, что в качестве welcome-file-list> у нас отмечен наш сервлет MainFrameServlet. Т.е. когда вы запустите проект он будет отображаться сразу же. Мелочь, а приятно.

 

ЧТО ЕЩЕ ОЧЕНЬ ВАЖНО !!!

Вам надо скопировать файлы из директории tld (надеюсь вы не забыли – это наши тэги для управления контентом в JSP.

 

Ваш проект находится где-то по такому пути

C:\Documents and Settings\<user>\My Documents\NetBeansProjects\StudentsApp\StudentsApp-war\web

 

Вот здесь и надо копировать наш каталог tld – в WEB-INF. NetBeans «подхватит» добавленные файлы.

4 comments to «Студенческий отдел кадров» в виде Enterprise-приложения

  • Vasyl Khrystiuk  says:

    В последних версиях сервера больше не надо носиться с jstl библиотекой. Она идет в комплекте с GlassFish.

    • admin  says:

      Да, статьи устарели. Попробую сделать новый вариант.

  • Sergey  says:

    В файле MainFrameServlet.java в методе processRequest() при добавлении студента (if answer==1), если явно не установить пол студента, то при нажатии кнопки Add бросается NullPointerException.
    Также не понял почему мы в jsp-файлах установили кодировку windows-1251? Мозила и Хром не могут ее отобразить. Если используем utf-8, то все работает корректно, только нужно еще в сервлетах в processRequest вызвать req.setCharacterEncoding(«UTF-8»).

    • AlexanderS  says:

      По поводу NullPointerException при нажатии кнопки Add:
      когда в MainFrameServlet в блоке после if (answer==1) выполняется команда Students s = new Students(), то поле Character sex созданного объекта класса Students содержит значение по-умолчанию, т.е. null. Затем в форме StudentForm в методе initFromStudent(Students st) происходит попытка вызвать метод equals() на объекте, содержащем null:
      st.getSex().equals(new Character(‘М’)).
      Можно, например, в условии сделать проверку на null:
      st.getSex() != null && st.getSex().equals(new Character(‘М’))

Leave a reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.