Spis treści

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:

4. Określenie scenariuszy użycia

  1. Scenariusze dla Użytkownika
    1. 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
    2. Założenie konta:
      • Wejście na stronę
      • Kliknięci w panel 'Rejestracja!'
      • Wprowadzenie danych użytkownika
      • Potwierdzenie założenia konta
  2. Scenariusze dla Użytkownika posiadającego firmę
    1. 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
    2. 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
    3. 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:

6. Analiza hierarchii funkcji projektowanej aplikacji (FHD – Functional Hierarchy Diagram)

7. Budowa i analiza diagramu przepływu danych (DFD – Data Flow Diagram)

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<Opinion> opinions;
 
	@OneToMany(mappedBy="owner", targetEntity=Course.class, cascade=CascadeType.ALL, fetch=FetchType.LAZY)
	private Set<Course> 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<Stop> 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<Company> companies;
}

9. Projektowanie powiązań (relacji) pomiędzy encjami (ERD)

10. Projekt diagramów STD (State Transition Diagram)

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:

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

-formularz logowania użytkownika

-formularz zakładania firmy przez użytkownika

-formularz edycji danych użytkownika

-formularz dodawania komentarzy

-formularz dodawania połączenia

-formularz wyszukiwania połączeń

17. Zdefiniowanie dokumentów do przetwarzania i prezentacji danych

-prezentacja wyników wyszukiwania

-prezentacja dodanej trasy

-prezentacja aktualnosci

-prezentacja komentarzy