====== Ogólnopolska baza połączeń minibusowych ======
Autorzy: **Jakub Gorzała, Łukasz Kowalski**
----
===== 1. Sformułowanie zadania projektowego =====
Projekt bazy danych, która będzie wykorzystywana w projekcie z przedmiotu Technologie i programowanie WWW. Projekt ten ma na celu stworzenie portalu zawierającego rozkłady jazdy minibusów z całej polski.
===== 2. Analiza stanu wyjściowego =====
W sieci istnieje strona o podobnej tematyce, lecz posiada ona sporo wad. Po pierwsze jest wykonana w bardzo prostej technologii (zwykły html + css), jest nieczytelna przez co prezentuje się bardzo nie atrakcyjnie i nie wzbudza zainteresowania. Nie jest aktualizowana, więc informacje na niej zawarte mogą być mylące dla użytkowników. Strona w głównej mierze jest zbiorem linków do poszczególnych przewoźników, a nie centralnym zbiorem rozkładów, przez co wyszukiwanie interesującego połączenia jest trudne. Storna nie posiada możliwości wystawiania opinii ani komentarzy przewoźnikom, a takie informacje mogły by być przydatne.
===== 3. Analiza wymagań użytkownika (wstępna) =====
Główne funkcjonalności portalu:
* zarejestrowanie nowej firmy przewozowej + podstawowych informacji adresowych
* dodanie kursów oferowanych przez tą firmę
* możliwość wyszukiwania kursów filtrując po przystankach z miejscowości A do B
* możliwość dodania komentarzy dla poszczególnych firm przez użytkowników
* moduł rejestracji użytkowników
* dodawanie cen biletów na poszczególnych trasach
* powiadomienia mailowe odnośnie nowych przewoźników w regionie bądź zmian w rozkładach jazdy
===== 4. Określenie scenariuszy użycia =====
- **Scenariusze dla Użytkownika**
- Wyszukanie połączenia:
* Wejście na stronę
* Przejście na zakładkę 'Szukaj busa'
* Wprowadzenie danych przystanku początkowego i końcowego
* Podanie godziny odjazdu lub przyjazdu
* Uruchomienie wyszukiwania i przeglądnięcie wyników
- Założenie konta:
* Wejście na stronę
* Kliknięci w panel 'Rejestracja!'
* Wprowadzenie danych użytkownika
* Potwierdzenie założenia konta
- **Scenariusze dla Użytkownika posiadającego firmę**
- Założenie firmy
* Wejście na stronę
* Zalogowanie się
* Kliknięcie w panel 'Dodaj firmę'
* Wprowadzenie nazwy firmy oraz maila firmowego
* Potwierdzenie dodania firmy
- Wprowadzenie trasy
* Wejście na stronę
* Zalogowanie się
* Wybranie zakładki 'Dodaj linię'
* Wprowadzenie kolejnych przystanków, czasów odjazdu oraz cen biletów
* Potwierdzenie dodania linii
- Zarządzanie trasami
* Wejście na stronę
* Zalogowanie się
* Wybranie zakładki 'Połączenia'
* Edycja/usuwanie zdefiniowanych połączeń
===== 5. Identyfikacja funkcji =====
Baza danych będzie przechowywać informacje o:
* kontach użytkowników
* zarejestrowanych firmach
* przystankach
* zdefiniowanych połączeniach
* opiniach o firmie
===== 6. Analiza hierarchii funkcji projektowanej aplikacji (FHD – Functional Hierarchy Diagram) =====
{{:pl:dydaktyka:ztb:2010:projekty:minibus:fhd.png|}}
===== 7. Budowa i analiza diagramu przepływu danych (DFD – Data Flow Diagram) =====
* Level 0
{{:pl:dydaktyka:ztb:2010:projekty:minibus:dfd_1.png|}}
* Level 1
{{:pl:dydaktyka:ztb:2010:projekty:minibus:dfd_2.png|}}
* Level 2 - Wyszukiwanie busa
{{:pl:dydaktyka:ztb:2010:projekty:minibus:dfd_3_1.png|}}
* Level 2 - Zarządzanie połączeniami
{{:pl:dydaktyka:ztb:2010:projekty:minibus:dfd_3_2.png|}}
* Level 2 - Dodawanie komentarza
{{:pl:dydaktyka:ztb:2010:projekty:minibus:dfd_3_3.png|}}
===== 8. Wybór encji (obiektów) i ich atrybutów =====
@Entity
@Table(name="COMPANIES")
@NamedQueries({
@NamedQuery(name="findCompanyByName", query="SELECT c FROM Company c WHERE c.name = :name"),
@NamedQuery(name="findCompanyByOwnerName", query="SELECT c FROM Company c WHERE c.owner.name = :name")
})
public class Company implements Serializable {
private static final long serialVersionUID = 5074588959885714521L;
@GeneratedValue(strategy=GenerationType.AUTO)
private long companyid;
@Column(nullable=false)
private String name;
@Column(nullable=false)
private String mail;
@ManyToOne
private User owner;
@OneToMany(mappedBy="company", targetEntity=Opinion.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Set opinions;
@OneToMany(mappedBy="owner", targetEntity=Course.class, cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private Set courses;
}
@Entity
@Table(name="COURSES")
@NamedQuery(name="findCourseByCompany", query="SELECT c FROM Course c WHERE c.owner.name = :name")
public class Course implements Serializable {
private static final long serialVersionUID = 3008699718560976506L;
@GeneratedValue(strategy=GenerationType.AUTO)
private long courseid
@OneToOne
private Company owner;
@Column(nullable=true)
private String description;
@OneToMany(mappedBy="course", targetEntity=Stop.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private List stops;
}
@Entity
@Table(name="OPINIONS")
@NamedQuery(name="findOpinionByCompany", query="SELECT o FROM Opinion o WHERE o.company.name = :name")
public class Opinion implements Serializable {
private static final long serialVersionUID = 2475121744579807544L;
@GeneratedValue(strategy=GenerationType.AUTO)
private long opinionid;
@ManyToOne
private Company company;
@Column(nullable=true)
private boolean positive;
@Column(nullable=true)
private String description;
}
@Entity
@Table(name="PLACES")
@NamedQueries({
@NamedQuery(name="findPlaceByName", query="SELECT p FROM Place p WHERE p.city = :city AND p.name = :name"),
@NamedQuery(name="autocompletePlace", query="SELECT p FROM Place p WHERE p.city LIKE :city AND p.name LIKE :name"),
@NamedQuery(name="autocompletePlaceByCity", query="SELECT p FROM Place p WHERE p.city LIKE :city"),
@NamedQuery(name="autocompletePlaceByName", query="SELECT p FROM Place p WHERE p.name LIKE :name")
})
public class Place implements Serializable {
private static final long serialVersionUID = 7561920390812143011L;
@GeneratedValue(strategy=GenerationType.AUTO)
private long placeid;
@Column(nullable=false)
private String city;
@Column(nullable=false)
private String name;
@Column(nullable=true)
private BigDecimal lon;
@Column(nullable=true)
private BigDecimal lat;
}
@Entity
@Table(name="STOPS")
@NamedQuery(name="findStopByPlace", query="SELECT s FROM Stop s WHERE s.place.city = :city and s.place.name = :name")
public class Stop implements Serializable {
private static final long serialVersionUID = 2015220800633676479L;
@GeneratedValue(strategy=GenerationType.AUTO)
private long stopid;
@ManyToOne
private Course course;
@OneToOne
private Place place;
@Column(nullable=false)
private int orderNumber;
@Column(nullable=true)
private BigDecimal cost;
@Column(nullable=true)
private String hours;
}
@Entity
@Table(name="USERS")
public class User implements Serializable {
private static final long serialVersionUID = 8651753619995718647L;
@GeneratedValue(strategy=GenerationType.AUTO)
private long userid;
@Column(nullable=false)
private String name;
@Column(nullable=false)
private String password;
@Column(nullable=false)
private String mail;
@Column(nullable=false)
private int role = 1;
@OneToMany(mappedBy="owner", targetEntity=Company.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Set companies;
}
===== 9. Projektowanie powiązań (relacji) pomiędzy encjami (ERD) =====
{{:pl:dydaktyka:ztb:2010:projekty:minibus:erd2.png|}}
===== 10. Projekt diagramów STD (State Transition Diagram) =====
* Wyszukiwanie busa
{{:pl:dydaktyka:ztb:2010:projekty:minibus:std1.png|}}
* Dodawanie połączenia
{{:pl:dydaktyka:ztb:2010:projekty:minibus:std2.png|}}
===== 11. Projektowanie tabel, kluczy, kluczy obcych, powiązań między tabelami, indeksów =====
CREATE TABLE companies
(
id bigint NOT NULL,
"name" character varying(255) NOT NULL,
mail character varying(255) NOT NULL,
owner_id bigint,
CONSTRAINT companies_pkey PRIMARY KEY (id),
CONSTRAINT fk51e1f1bbedbce178 FOREIGN KEY (owner_id)
REFERENCES users (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
CREATE TABLE courses
(
id bigint NOT NULL,
description character varying(255),
hours character varying(255),
owner_id bigint,
CONSTRAINT courses_pkey PRIMARY KEY (id),
CONSTRAINT fk63e4af986eae0d5e FOREIGN KEY (owner_id)
REFERENCES companies (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
CREATE TABLE opinions
(
id bigint NOT NULL,
positive boolean,
description character varying(255),
company_id bigint,
CONSTRAINT opinions_pkey PRIMARY KEY (id),
CONSTRAINT fk176ead31d905f754 FOREIGN KEY (company_id)
REFERENCES companies (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
CREATE TABLE places
(
id bigint NOT NULL,
city character varying(255) NOT NULL,
"name" character varying(255) NOT NULL,
lon numeric(19,2),
lat numeric(19,2),
CONSTRAINT places_pkey PRIMARY KEY (id)
)
CREATE TABLE stops
(
id bigint NOT NULL,
ordernumber integer NOT NULL,
"cost" numeric(19,2),
lag numeric(19,2),
place_id bigint,
course_id bigint,
CONSTRAINT stops_pkey PRIMARY KEY (id),
CONSTRAINT fk4b9009137509994 FOREIGN KEY (place_id)
REFERENCES places (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fk4b90091894e45e0 FOREIGN KEY (course_id)
REFERENCES courses (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
CREATE TABLE users
(
id bigint NOT NULL,
"name" character varying(255) NOT NULL,
"password" character varying(255) NOT NULL,
mail character varying(255) NOT NULL,
"role" integer NOT NULL,
CONSTRAINT users_pkey PRIMARY KEY (id)
)
CREATE SEQUENCE hibernate_sequence
INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1;
===== 12. Analiza zależności funkcyjnych i normalizacja tabel =====
Wydaje się, że baza danych spełnia założenia 3NF. Wynika to z faktu, że przechowywane w niej dane są istnotnie atomiczne - z punktu widzenia implementacji projektu. W każdej tabeli atrybuty są w pełni bezpośrednio zależne od klucza głównego. Generalnie baza była projektowana tak by przy możlie maksymalnej funkcjonalności tabel, zapewnić trzecią postać normalną.
===== 13. Projektowanie operacji na danych =====
Kwerendy i zapytania wynikają z mechanizmu mapowania obiektowo relacyjnego w j2ee i są poniekąd dostarczone przez klasę EntityManager standardu JPA Hibernate. Pozostałe zapytania w celu optymalizacji wydajności pracy aplikacji zrealizowane zostały jako NamedQuery - zapytania prekompilowane i stworzone przy użyciu składni HQL - Hibernate Query Language. Można je zobaczyć nad kodem encji do których przynależą.
===== RAPORT KOŃCOWY =====
===== 14. Stos technologiczny =====
Aplikacja zrealizowana jest na bazie wzorca projektowego MVC (model widok kotroller).
Sklada sie z 3 wyraznie wyrożnionych warstw:
* baza danych - Postrgres 8.3, Mapowanie relacyjno obiektowe standard Java JPA Persistence
* logika biznesowa - Zrealizowana za pomocą technologii EJB 3.0
* widok - Zrealizowany za pomocą JSF (java server faces 1.2) z nakładką jQery oraz jQueryUI
===== 15. Implementacja bazy danych =====
Patrz punkt 11. Projektowanie tabel, kluczy, kluczy obcych, powiązań między tabelami, indeksów.
===== 16. Zdefiniowanie interfejsów do prezentacji, edycji i obsługi danych =====
-formularz rejestracji użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:minibus:rejestracja1.png|}}
-formularz logowania użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:minibus:logowanie1.png|}}
-formularz zakładania firmy przez użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:minibus:dodawanie_firmy1.png|}}
-formularz edycji danych użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:minibus:moje_dane.png|}}
-formularz dodawania komentarzy
{{:pl:dydaktyka:ztb:2010:projekty:minibus:komentarze1.png|}}
-formularz dodawania połączenia
{{:pl:dydaktyka:ztb:2010:projekty:minibus:dodawanie_polaczenia1.png|}}
-formularz wyszukiwania połączeń
{{:pl:dydaktyka:ztb:2010:projekty:minibus:wyszukiwanie1.png|}}
===== 17. Zdefiniowanie dokumentów do przetwarzania i prezentacji danych =====
-prezentacja wyników wyszukiwania
{{:pl:dydaktyka:ztb:2010:projekty:minibus:wyszukiwanie1.png|}}
-prezentacja dodanej trasy
{{:pl:dydaktyka:ztb:2010:projekty:minibus:dodawanie_polaczenia2.png|}}
-prezentacja aktualnosci
{{:pl:dydaktyka:ztb:2010:projekty:minibus:aktualnosci1.png|}}
-prezentacja komentarzy
{{:pl:dydaktyka:ztb:2010:projekty:minibus:komentarze1.png|}}