• Nie Znaleziono Wyników

Instrukcja do przykładu z technologii Spring Data

N/A
N/A
Protected

Academic year: 2022

Share "Instrukcja do przykładu z technologii Spring Data"

Copied!
11
0
0

Pełen tekst

(1)

Instrukcja do przykładu z technologii Spring Data

Na seminarium zostanie przedstawione krok po kroku jak powstaje projekt oparty o tech- nologie Spring Data. Zostanie on wsparty o technologię Spring Boot, dzięki której w prosty sposób zostanie skonfigurowane połączenie z bazą danych. Do tego zostanie również wykorzystana relacyjna baza danych H2 w wersji “in memory”

Plan instrukcji:

1. Stworzenie minimalnej aplikacji pozwalającej na komunikacje z bazą danych.

2. Rozwinięcie aplikacji o różne funkcjonalności Spring Data.

1. Część dotycząca minimalnej konfiguracji

1.1. Inicjalizacja projektu Spring

Inicjalizacja projektu Spring za pomocą Spring Initializer dostępna na stronie https://start.spring.io/

Po wygenerowaniu projektu rozpakowujemy go i przenosimy do katalogu roboczego.

W Eclipse przechodzimy w menu do File -> Open project from File System... i następnie wska- zujemy we ścieżce źródło do naszego projektu.

(2)

1.2. Konfiguracja bazy danych

Konfiguracja odbywa się w prosty sposób dzięki użycia Spring Boota.

Modyfikujemy plik application.properties dodając następujący kod

# H2 Databse

spring.datasource.url=jdbc:h2:mem:testdb

spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa

spring.datasource.password=password

#JPA - implementacja Hibernate

spring.jpa.database-platform=org.hibernate.dia- lect.H2Dialect

spring.jpa.hibernate.ddl-auto=create

#Konsola Web bazy danych H2 spring.h2.console.enabled=true spring.h2.console.path=/h2-console server.port=8081

(3)

1.3. Tworzymy encje utrwalane w bazie danych Tworzymy klase Person.java w pakiecie zti.shop.model Klasa ta odwzorowuje obiekt w bazie danych.

Adnotacje:

@Entity - w JPA mówi o tym, że ta klasa jest odwzorowaniem encji w bazie danych

@Id - mówi o tym, że dane pole jest unikalne

@GeneratedValue - mówi o tym, że ta wartość ma być automatycznie generowana

package zti.shop.model;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

//Adnotacja @Entity w JPA mówi o tym, że ta klasa jest odwzorowaniem encji w bazie da- nych@Entity

public class Person {

//Adnotacja @Id mówi o tym, że dane pole jest unikalne

//Adnotacja @Generated value mówi o tym, że ta wartość ma być automatycznie generowana

@Id

@GeneratedValue private Long id;

private String firstName;

private String lastName;

public Long getId() { return id;

}

public void setId(Long id) { this.id = id;

}

public String getFirstName() { return firstName;

}public void setFirstName(String firstName) { this.firstName = firstName;

}

public String getLastName() { return lastName;

}

public void setLastName(String lastName) { this.lastName = lastName;

} }

(4)

1.4. Stworzenie repozytorium dla encji

Jest to interface rozszerzający inny interfejs CrudRepository<encja,typ identyfikatora>, który dostarcza nam zbiór podstawowych metod do zarządzania encjami w bazie danych.

1.5. Stworzenie komponentu

Komponent będzie wykorzystywał zaimplementowane przez nas fukcjonalności Tworzymy plik RunAtStart.java w pakiecie zti.shop

package zti.shop.repository;

import org.springframework.data.repository.CrudRepository;

import zti.shop.model.Person;

public interface PersonRepository extends CrudRepository <Person, Long>{

}

package zti.shop;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import zti.shop.model.Person;

import zti.shop.repository.PersonRepository;

@Component

public class RunAtStart {

private final PersonRepository personRepository;

public RunAtStart(PersonRepository personRepository) { super();

this.personRepository = personRepository;

}

@PostConstruct

public void runAtStart(){

Person person1 = new Person();

person1.setFirstName("Adam");

person1.setLastName("Nowak");

personRepository.save(person1);

System.out.println(person1);

} }

(5)

2. Cześć rozwijająca aplikacje o różne funkcjonalności Spring Data

2.1. Dodajemy encję produktu product.java w pakiecie model

package zti.shop.model;

import java.util.List;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.ManyToMany;

@Entity

public class Product {

@Id

@GeneratedValue private Long id;

private String name;

private int price;

@ManyToMany(mappedBy = "products") private List<Person> people;

public Long getId() { return id;

}

public void setId(Long id) { this.id = id;

}

public String getName() { return name;

}

public void setName(String name) { this.name = name;

}

public int getPrice() { return price;

}

public void setPrice(int price) { this.price = price;

}

public List<Person> getPeople() { return people;

}

public void setPeople(List<Person> people) { this.people = people;

}

@Override

public String toString() {

return "Product [id=" + id + ", name=" + name + ", price=" + price + ", people=" + people +

"]";

} }

(6)

2.2. Edydutjemy encję person.java określając relację wiele do wielu z encją product.

package zti.shop.model;

import java.util.List;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.ManyToMany;

@Entity

public class Person {

@Id

@GeneratedValue private Long id;

private String firstName;

private String lastName;

@ManyToMany

private List<Product> products;

public List<Product> getProducts() { return products;

}

public void setProducts(List<Product> products) { this.products = products;

}

public Long getId() { return id;

}

public void setId(Long id) { this.id = id;

}

public String getFirstName() { return firstName;

}

public void setFirstName(String firstName) { this.firstName = firstName;

}

public String getLastName() { return lastName;

}

public void setLastName(String lastName) { this.lastName = lastName;

}

@Override

public String toString() {

return "Person [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", prod- ucts=" + products

+ "]";

} }

(7)

2.3. Modyfikujemy repozytorium dla encji Person

Do encji person dodane zostało zapytanie wbudowane findByFirstName(String firstName), które na podstawie naz- wy funkcji jest generowane przez Spring Data. Funkcja zwraca użytkowników z bazy danych o podanym imieniu w argumencie. Zapytania wbudowane są generowane na podstawie słów kluczowych takich jak findBy oraz nazw pól z bazy danych, czyli FirstName. Pełny zestaw możliwości jest dostępny w dokumentacji Spring Data.

2.4. Tworzymy repozytorium dla encji Product w pakiecie repository.

package zti.shop.repository;

import org.springframework.data.jpa.repository.Query;

import org.springframework.data.repository.CrudRepository;

import zti.shop.model.Person;

public interface PersonRepository extends CrudRepository <Person, Long>{

Iterable<Person> findByFirstName(String firstName);

// @Query(value = "Select p.firstName from Person p") // Iterable<Person> findAll();

}

package zti.shop.repository;

import org.springframework.data.repository.CrudRepository;

import zti.shop.model.Product;

public interface ProductRepository extends CrudRepository <Product, Long>{

}

(8)

2.5. Modyfikujemy RunAtStart.java

W rozszerzonym komponencie uzupełniamy dodatkowe pola dla stworzonych encji.

package zti.shop;

import java.util.ArrayList;

import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import zti.shop.model.Person;

import zti.shop.model.Product;

import zti.shop.repository.PersonRepository;

import zti.shop.repository.ProductRepository;

@Component

public class RunAtStart {

private final PersonRepository personRepository;

private final ProductRepository productRepository;

public RunAtStart(PersonRepository personRepository, ProductRepository productRepository) { super();

this.personRepository = personRepository;

this.productRepository = productRepository;

}

@PostConstruct

public void runAtStart(){

Person person1 = new Person();

person1.setFirstName("Adam");

person1.setLastName("Nowak");

Person person2 = new Person();

person2.setFirstName("Zbigniew");

person2.setLastName("Brzezinski");

Product bike = new Product();

Product lego = new Product();

bike.setName("rower");

bike.setPrice(200);

lego.setName("lego");

lego.setPrice(90);

List<Product> order1= new ArrayList<Product>();

order1.add(bike);

order1.add(lego);

List<Product> order2= new ArrayList<Product>();

order2.add(lego);

person1.setProducts(order1);

productRepository.saveAll(order1);

personRepository.save(person1);

personRepository.save(person2);

System.out.println(person1);

} }

(9)

2.6. Tworzymy kontroler ShopController.java do naszej aplikacji obsługujący zapytania do serwera.

Tworzymy plik ShopController.java w pakiecie controller.

package zti.shop.controller;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.CrossOrigin;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.bind.annotation.RestController;

import zti.shop.model.Person;

import zti.shop.model.Product;

import zti.shop.repository.PersonRepository;

import zti.shop.repository.ProductRepository;

@RequestMapping("api/v1/shop")

@RestController

@CrossOrigin("*")

public class ShopController {

@Autowired

private PersonRepository personRepository;

@Autowired

private ProductRepository productRepository;

@GetMapping(path = "/person")

public @ResponseBody Iterable<Person> getAllPeople(){

return personRepository.findAll();

}

@GetMapping(path = "/product")

public @ResponseBody Iterable<Product> getAllProducts(){

return productRepository.findAll();

}

@GetMapping(path = "person/firstname/{firstNameValue}")

public @ResponseBody Iterable<Person> getPersonByFirstName(@PathVariable("firstNameValue") String firstNameValue){

return personRepository.findByFirstName(firstNameValue);

}

@PostMapping(path = "person/{firstNameValue}/{lastNameValue}")

public void addPerson(@PathVariable("firstNameValue") String firstNameValue, @PathVariable("lastNa- meValue") String lastNameValue){

Person person = new Person();

person.setFirstName(firstNameValue);

person.setLastName(lastNameValue);

personRepository.save(person);

} }

(10)

2.7 Sprawdzamy działanie zapytań do serwera

Przez połączenie wiele do wielu encji product i person we zwróconym JSONie powstaje zapętlo- na zależność, która przy przekształcaniu tabel z bazy:

w dwa obiekty java, powoduje przesyłanie zapętlony plik json.

(11)

W takich jak ta sytuacjach przydatne jest tworzenie zapytań własnych, którymi programista może nadpisywać te domyślnie generowane przez Spring Data, jak również tworzyć nowe, które są bardziej złożone i dostosowane do stworzonej bazy danych.

2.8 Dodanie zapytania własnego do PersonRepozytory.java

W ten sposób zostaje nadpisana funkcja findAll() dla encji Person. W rezultacie powtórzenie wy- konania zapytania zwróci dane w prawidłowym jsonie.

package zti.shop.repository;

import org.springframework.data.jpa.repository.Query;

import org.springframework.data.repository.CrudRepository;

import zti.shop.model.Person;

public interface PersonRepository extends CrudRepository <Person, Long>{

Iterable<Person> findByFirstName(String firstName);

@Query(value = "Select p.firstName from Person p") Iterable<Person> findAll();

}

Cytaty

Powiązane dokumenty

Dla systemów operacyjnych stosowanych w systemach wbudowanych wymaga si˛e nast˛epuj ˛ acych zasobów pami˛eci:.. • QNX: ma najmniejsze wymagania

Czy istnieje taki k-elementowy zbiór S wierzchołków grafu G, że każdy z pozostałych wierzchołków jest osiągalny z jakiegoś wierzchołka należącego do S drogą składającą się

została złożona po terminie składania ofert dodatkowych określonym przez Zamawiającego w wezwaniu do złożenia tych ofert.. W przypadku uznania za najkorzystniejszą

2005-10-27 Definiowanie typów dokumentów – część 3: XML Schema 2. Wbudowane

Wykorzystuj ˛ ac przerwanie int0 zrealizuj system, który zlicza wci´sni˛ecia przycisku i wy-..

Klasa HibernateTemplate jest bezpieczna ze względu na wątki, dlatego można zadeklarować jeden obiekt tej klasy w pliku z konfiguracją ziaren dla platformy Hibernate (czyli w

4) Pamięć lub urządzenie wyjścia odczytują dane z magistrali danych. Pamięć umieszcza dane pod adresem odczytanym z magistrali adresowej. Dla urządzeń wyjścia adres określa

instrumenty pierwotne, instrumenty pochodne i instrumenty wbudowane. Wbudowany instrument pochodny jest składnikiem hybrydowego instrumentu, który zawiera umowę zasadniczą