Commit 216f7078 by Patryk Czarnik

Pozostałe przykład ySpringData

parent c7c1742d
package alx.data;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import alx.model.Employee;
@Controller
public class Controller0 {
@Autowired
private Repository0_Memory repository;
@GetMapping("/emps0")
public String showExampleEmployee(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
}
package alx.data;
import java.util.List;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import alx.model.Employee;
@Controller
@RequestMapping("/emps1")
public class Controller1_EM {
/* W tej wersji Controller bezpośrednio korzysta z technologii JPA/Hibernate.
* Ułatwieniem jest to, że Spring automatycznie "wstryknie" nam obiekt EntityManager.
*/
@Autowired
private EntityManager em;
@GetMapping
public String showAll(Model model) {
TypedQuery<Employee> query = em.createNamedQuery("Employee.findAll", Employee.class);
List<Employee> emps = query.getResultList();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Employee emp = em.find(Employee.class, employeeId);
model.addAttribute("emps", List.of(emp));
return "employees.html";
}
}
package alx.data;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import alx.model.Employee;
@Controller
@RequestMapping("/emps2")
public class Controller2 {
@Autowired
private Repository2 repository;
@GetMapping
public String showAll(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Employee emp = repository.findOne(employeeId);
model.addAttribute("emps", List.of(emp));
return "employees.html";
}
@GetMapping("/by_name")
public String showByName(Model model,
@RequestParam("name") String name) {
List<Employee> emps = repository.findByLastName(name);
model.addAttribute("emps", emps);
return "employees.html";
}
}
package alx.data;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import alx.model.Employee;
@Controller
@RequestMapping("/emps3")
public class Controller3 {
/* Aby bezpośrednio w Controllerze nie używać kodów dot. Hibernate, SQL itd...
* wydzielam operacje bazodanowe do oddzielnej klasy, opisanej jako Repository
* i wstrzykuję referencję do repozytorium tutaj w controllerze.
* W doatku robię to porzez interfejs (zgodne z najlepszymi praktykami Springa),
* aby ułatwić podmianę implementacji na inną.
*/
@Autowired
private Repository3_Interface repository;
@GetMapping
public String showAll(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Employee emp = repository.findOne(employeeId);
model.addAttribute("emps", List.of(emp));
return "employees.html";
}
@GetMapping("/by_name")
public String showByName(Model model,
@RequestParam("name") String name) {
List<Employee> emps = repository.findByLastName(name);
model.addAttribute("emps", emps);
return "employees.html";
}
}
package alx.data;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import alx.model.Employee;
@Controller
@RequestMapping("/emps4")
public class Controller4 {
@Autowired
private Repository4 repository;
@GetMapping
public String showAll(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Optional<Employee> emp = repository.findById(employeeId);
List<Employee> emps;
if (emp.isPresent()) {
emps = List.of(emp.get());
} else {
emps = List.of();
}
model.addAttribute("emps", emps);
return "employees.html";
}
}
package alx.data;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import alx.model.Employee;
@Controller
@RequestMapping("/emps5")
public class Controller5 {
@Autowired
private Repository5 repository;
@GetMapping("/all")
public String showAll(Model model) {
List<Employee> emps = repository.findAll();
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/by_id/{id}")
public String showOne(Model model,
@PathVariable("id") Integer employeeId) {
Optional<Employee> emp = repository.findById(employeeId);
List<Employee> emps;
if (emp.isPresent()) {
emps = List.of(emp.get());
} else {
emps = List.of();
}
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/by_name")
public String showByName(Model model,
@RequestParam("name") String name) {
List<Employee> emps = repository.findByLastName(name);
model.addAttribute("emps", emps);
return "employees.html";
}
// http://localhost:8080/emps5/by_job/IT_PROG
@GetMapping("/by_job/{job}")
public String getEmployeesByJobId(Model model,
@PathVariable("job") String jobId) {
List<Employee> emps = repository.findByJob_JobId(jobId);
model.addAttribute("emps", emps);
return "employees.html";
}
// http://localhost:8080/emps5/by_city/Oxford
@GetMapping("/by_city/{city}")
public String getEmployeesByCity(Model model,
@PathVariable("city") String city) {
List<Employee> emps = repository.findByDepartment_Location_City(city);
model.addAttribute("emps", emps);
return "employees.html";
}
// http://localhost:8080/emps5/by_salary?min=5000&max=10000
@GetMapping("/by_salary")
public String getEmployeesBySalary(Model model,
@RequestParam(name="min", defaultValue="0") BigDecimal min,
@RequestParam(name="max", defaultValue="1000000000") BigDecimal max) {
List<Employee> employees = repository.findBySalary(min, max);
model.addAttribute("emps", employees);
return "employees.html";
}
@GetMapping("/by_year/{year}")
public String getEmployeesByYear(Model model,
@PathVariable("year") int year) {
List<String> names = repository.namesByYear(year);
model.addAttribute("names", names);
return "names.html";
}
@GetMapping("/zara")
public String zarabiajacy(Model model,
@RequestParam("id") int id) {
List<Employee> emps = repository.zarabiajacyWiecejNiz(id);
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/szef/{id}")
@ResponseBody
public String szef(@PathVariable("id") Integer idPracownika) {
return repository.nazwiskoSzefa(idPracownika);
}
@GetMapping("/save/{id}")
public String modify(Model model,
@PathVariable("id") Integer idPracownika,
@RequestParam(value="salary", required=false) BigDecimal newSalary,
@RequestParam(value="first_name", required=false) String newFirstName,
@RequestParam(value="last_name", required=false) String newLastName) {
Optional<Employee> found = repository.findById(idPracownika);
List<Employee> emps;
if(found.isPresent()) {
Employee emp = found.get();
if(newSalary != null)
emp.setSalary(newSalary);
if(newFirstName != null)
emp.setFirstName(newFirstName);
if(newLastName != null)
emp.setLastName(newLastName);
repository.save(emp);
emps = List.of(emp);
} else {
emps = List.of();
}
model.addAttribute("emps", emps);
return "employees.html";
}
@GetMapping("/move/{id}")
@ResponseBody
public String modify(Model model,
@PathVariable("id") Integer idPracownika,
@RequestParam(value="dep", required=false) int newDep,
@RequestParam(value="job", required=false) String newJob) {
repository.moveEmployee(idPracownika, newDep, newJob);
return "Przeniesiono";
}
}
......@@ -7,6 +7,7 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import java.util.Optional;
......@@ -32,4 +33,12 @@ public class Controller9 {
}
return "employees.html";
}
@GetMapping("/by_name")
public String showByName(Model model,
@RequestParam("name") String name) {
List<Employee> emps = repo.findByLastName(name);
model.addAttribute("emps", emps);
return "employees.html";
}
}
package alx.data;
import java.math.BigDecimal;
import java.util.List;
import org.springframework.stereotype.Repository;
import alx.model.*;
/* Klasa pełniąca rolę repozytoium, czyli dostraczanie danych,
* ale zaimplementowana bez bazy danych - po prostu zwraca przykładowe obiekty.
*/
@Repository
public class Repository0_Memory {
public List<Employee> findAll() {
Employee emp = exampleEmployee1();
return List.of(emp);
}
private Employee exampleEmployee1() {
Employee emp = new Employee();
emp.setFirstName("Jan");
emp.setLastName("Kowalski");
emp.setSalary(BigDecimal.valueOf(12345));
emp.setJob(exampleJob());
emp.setDepartment(exampleDepartment());
return emp;
}
private Department exampleDepartment() {
Location loc = new Location();
loc.setCity("Warszawa");
Department dep = new Department();
dep.setDepartmentName("Szkolenia");
dep.setLocation(loc);
return dep;
}
private Job exampleJob() {
Job job = new Job();
job.setJobTitle("Trainer");
return job;
}
}
package alx.data;
import java.util.List;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import alx.model.Employee;
@Repository
public class Repository2 {
@Autowired
private EntityManager em;
public List<Employee> findAll() {
TypedQuery<Employee> query = em.createNamedQuery("Employee.findAll", Employee.class);
List<Employee> emps = query.getResultList();
return emps;
}
public Employee findOne(int employeeId) {
return em.find(Employee.class, employeeId);
}
public List<Employee> findByLastName(String lastName) {
TypedQuery<Employee> query = em.createQuery(
"SELECT emp FROM Employee emp WHERE emp.lastName = :name", Employee.class);
query.setParameter("name", lastName);
List<Employee> emps = query.getResultList();
return emps;
}
}
package alx.data;
import java.util.List;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import alx.model.Employee;
@Repository
public class Repository3_Impl implements Repository3_Interface {
@Autowired
private EntityManager em;
@Override
public List<Employee> findAll() {
TypedQuery<Employee> query = em.createNamedQuery("Employee.findAll", Employee.class);
List<Employee> emps = query.getResultList();
return emps;
}
@Override
public Employee findOne(int employeeId) {
return em.find(Employee.class, employeeId);
}
@Override
public List<Employee> findByLastName(String lastName) {
TypedQuery<Employee> query = em.createQuery(
"SELECT emp FROM Employee emp WHERE emp.lastName = :name", Employee.class);
query.setParameter("name", lastName);
List<Employee> emps = query.getResultList();
return emps;
}
}
package alx.data;
import java.util.List;
import alx.model.Employee;
public interface Repository3_Interface {
List<Employee> findAll();
Employee findOne(int employeeId);
List<Employee> findByLastName(String lastName);
}
\ No newline at end of file
package alx.data;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import alx.model.Employee;
@Repository
public interface Repository4 extends JpaRepository<Employee, Integer> {
// Spring sam tworzy instancję tego interfejsu, która zawiera implementację wszystkich standardowych metod
}
package alx.data;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import alx.model.Employee;
@Repository
public interface Repository5 extends JpaRepository<Employee, Integer> {
List<Employee> findByLastName(String name);
List<Employee> findByLastNameContainingIgnoringCase(String name);
List<Employee> findByJob_JobId(String jobId);
// employee.getDepartment().getLocation().getCity()
// ale w zapytaniu zostanie to zamienione na SQL, który JOIN-em dołącza tabele departments i locations i w WHERE sprawdza city
List<Employee> findByDepartment_Location_City(String city);
// Zapytanie w składni JPQL
@Query("SELECT emp FROM Employee emp WHERE emp.salary BETWEEN :min AND :max ORDER BY emp.salary")
List<Employee> findBySalary(BigDecimal min, BigDecimal max);
@Query(nativeQuery=true,
value="SELECT first_name || ' ' || last_name"
+ " FROM employees"
+ " WHERE extract(year FROM hire_date) = :year"
+ " ORDER BY last_name")
List<String> namesByYear(int year);
// W ramach takiego interfejsu można też pisać metody z własną implementacją.
// Tu przykład już nie bazodanowy...
default List<Integer> losowe(int limit, int ilosc) {
return ThreadLocalRandom.current().ints(ilosc, 0, limit).boxed().collect(Collectors.toList());
}
// podobno tak wygląda wywołanie procedury składowanej, ale nam nie działa
@Query(nativeQuery=true, value="CALL przenies_pracownika(:idPracownika, :newDep, :newJob)")
void moveEmployee(Integer idPracownika, int newDep, String newJob);
@Query(nativeQuery=true, value="SELECT zarabiajacy_wiecej_niz(:id)")
List<Employee> zarabiajacyWiecejNiz(int id);
@Query(nativeQuery=true, value="SELECT nazwisko_szefa(:idPracownika)")
String nazwiskoSzefa(Integer idPracownika);
}
......@@ -2,6 +2,11 @@ package alx.data;
import alx.model.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
public interface Repository9 extends JpaRepository<Employee, Integer> {
List<Employee> findByLastName(String name);
}
......@@ -51,7 +51,37 @@
</ul>
<h2>Spring Data</h2>
<p><a th:href="@{/emps9}">TERAZ</a></p>
<ul>
<li><a href="/emps0">InMemoryRepository</a></li>
<li><a href="/emps1">emps1</a> - wersja z bespośrednio użytym JPA</li>
<li><a href="/emps1/100">emps1/100</a> - odczyt jednego pracownika po id</li>
<li><a href="/emps2">emps2</a> - wersja z użyciem JPA wyciągniętym do osobnej klasy @Repository</li>
<li><a href="/emps2/100">emps2/100</a> - odczyt jednego pracownika po id</li>
<li><a href="/emps2/by_name?name=King">emps2/by_name?last_name=King</a> - odczyt pracowników po nazwisku, przykład <strong>Query</strong></li>
<li><a href="/emps3">emps3</a> - j.w. ale interfejs</li>
<li><a href="/emps3/100">emps3/100</a> - odczyt jednego pracownika po id</li>
<li><a href="/emps3/by_name?name=King">emps3/by_name?last_name=King</a> - odczyt pracowników po nazwisku, przykład <strong>Query</strong></li>
<li><a href="/emps4">emps4</a> - Spring Data JpaRepository – domyślny interfejs</li>
<li><a href="/emps4/100">emps4/100</a> - odczyt jednego pracownika po id</li>
<li><a href="/emps5/all">emps5</a> - Spring Data JpaRepository – rozszerzony interfejs</li>
<li><a href="/emps5/by_id/101">emps5/by_id/101</a> - wg id</li>
<li><a href="/emps5/by_name?name=King">emps5/by_name?last_name=King</a> - odczyt pracowników po nazwisku, przykład <strong>Query</strong></li>
<li><a href="/emps5/by_job/ST_CLERK">/by_job/ST_CLERK</a> - wg stanowiska
<li><a href="/emps5/by_city/Seattle">emps5/by_city/Seattle</a> - wg miasta</li>
<li><a href="/emps5/by_salary?min=5000&amp;max=10000">emps5/by_salary</a> - wg pensji</li>
<li><a href="/emps5/by_year/1999">emps5/by_year</a> - wg roku zatrudneinia - przykład <strong>native query</strong></li>
<li><a href="/emps5/szef/105">szef/105</a> - nazwisko sefa (przykład własnej funkcji)
<li><a href="/emps5/zara/?id=103">zara?id=103</a> - zarabiający więcej niż (przykład własnej funkcji)
<li><a href="/emps5/move/110?dep=90&job=AD_PRES">move</a> - przenieś pracownika
</ul>
<p>Pisane <a th:href="@{/emps9}">TERAZ</a></p>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment