Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions L28-springDataJdbc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
id ("org.springframework.boot")
}


dependencies {
dependencies {
implementation ("ch.qos.logback:logback-classic")
implementation ("org.flywaydb:flyway-core")
implementation ("org.postgresql:postgresql")
implementation ("com.google.code.findbugs:jsr305")
implementation ("org.springframework.boot:spring-boot-starter-data-jdbc")
implementation("org.postgresql:postgresql")

implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
implementation("org.flywaydb:flyway-core")

runtimeOnly("org.flywaydb:flyway-database-postgresql")

compileOnly ("org.projectlombok:lombok")
annotationProcessor ("org.projectlombok:lombok")
}
}
6 changes: 6 additions & 0 deletions L28-springDataJdbc/docker/runDb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
docker run --rm --name pg-docker \
-e POSTGRES_PASSWORD=pwd \
-e POSTGRES_USER=usr \
-e POSTGRES_DB=demoDB \
-p 5430:5432 \
postgres:17
53 changes: 53 additions & 0 deletions L28-springDataJdbc/src/main/java/ru/otus/AppRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package ru.otus;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import ru.otus.model.Address;
import ru.otus.model.Client;
import ru.otus.model.Phone;
import ru.otus.model.User;
import ru.otus.repository.AddressRepository;
import ru.otus.repository.ClientRepository;
import ru.otus.repository.PhoneRepository;
import ru.otus.repository.UserRepository;

@Component("actionDemo")
public class AppRunner implements CommandLineRunner {
private static final Logger log = LoggerFactory.getLogger(AppRunner.class);

private final ClientRepository clientRepository;
private final AddressRepository addressRepository;
private final PhoneRepository phoneRepository;
private final UserRepository userRepository;

public AppRunner(
UserRepository userRepository,
ClientRepository clientRepository,
AddressRepository addressRepository,
PhoneRepository phoneRepository) {
this.clientRepository = clientRepository;
this.addressRepository = addressRepository;
this.phoneRepository = phoneRepository;
this.userRepository = userRepository;
}

@Override
public void run(String... args) {

Client client = new Client("Иван");

Address address = new Address("ул. Ленина");
client.setAddress(address);

client.addPhone(new Phone("+7-900-111-22-33"));
client.addPhone(new Phone("+7-900-444-55-66"));

clientRepository.save(client);
addressRepository.save(address);

userRepository.save(new User("Пользователь", "user", "user"));
userRepository.save(new User("Administrator", "admin", "admin"));
}
}
23 changes: 23 additions & 0 deletions L28-springDataJdbc/src/main/java/ru/otus/DbServiceDemo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ru.otus;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/*
Полезные для демо ссылки

// Стартовая страница
http://localhost:8080

// Страница пользователей
http://localhost:8080/users

// REST сервис
http://localhost:8080/api/user/3
*/
@SpringBootApplication
public class DbServiceDemo {
public static void main(String[] args) {
SpringApplication.run(DbServiceDemo.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ru.otus.controller;

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 ru.otus.model.Client;
import ru.otus.repository.ClientRepository;

@Controller
public class ClientsController {

private final ClientRepository clientRepository;

@Autowired
public ClientsController(ClientRepository clientRepository) {
this.clientRepository = clientRepository;
}

@GetMapping("/clients")
public String clients(Model model) {
Iterable<Client> clients = clientRepository.findAll();
model.addAttribute("clients", clients);

return "clients";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package ru.otus.controller;

import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ru.otus.model.Address;
import ru.otus.model.Client;
import ru.otus.model.Phone;
import ru.otus.model.RequestAddPhone;
import ru.otus.model.RequestCreateClient;
import ru.otus.model.RequestEditClient;
import ru.otus.repository.AddressRepository;
import ru.otus.repository.ClientRepository;
import ru.otus.repository.PhoneRepository;

@RestController
@RequestMapping("/api/clients")
public class ClientsRestController {
private final ClientRepository clientRepository;
private final AddressRepository addressRepository;
private final PhoneRepository phoneRepository;

@Autowired
public ClientsRestController(
ClientRepository clientRepository, AddressRepository addressRepository, PhoneRepository phoneRepository) {
this.clientRepository = clientRepository;
this.addressRepository = addressRepository;
this.phoneRepository = phoneRepository;
}

@PostMapping
public ResponseEntity<?> createClient(@RequestBody RequestCreateClient request) {
if (request.getName() == null || request.getName().trim().isEmpty()) {
JsonResponse error = new JsonResponse("Invalid input", "Client name cannot be empty");
return ResponseEntity.status(400).body(error); // 400 Bad Request
}

Address address = new Address(request.getAddress());
Client client = new Client(request.getName());
client.setAddress(address);
client.addPhone(new Phone(request.getNumber()));
var savedClient = clientRepository.save(client);
addressRepository.save(address);

return ResponseEntity.status(201).body(savedClient);
}

@DeleteMapping("/{clientId}/phone/{phoneId}")
public ResponseEntity<?> deletePhone(@PathVariable Long clientId, @PathVariable Long phoneId) {
Optional<Client> client = clientRepository.findById(clientId);
if (client.isEmpty()) {
JsonResponse error = new JsonResponse("Invalid input", "Client not found");
return ResponseEntity.status(404).body(error);
}

phoneRepository.deleteById(phoneId);
return ResponseEntity.status(200).body(new JsonResponse("Phone deleted", "Phone Deleted"));
}

@PostMapping("/{clientId}/phone")
public ResponseEntity<?> addPhone(@PathVariable Long clientId, @RequestBody RequestAddPhone request) {
Optional<Client> client = clientRepository.findById(clientId);
if (client.isEmpty()) {
JsonResponse error = new JsonResponse("Invalid input", "Client not found");
return ResponseEntity.status(404).body(error);
}

if (request.getNumber() == null || request.getNumber().trim().isEmpty()) {
return ResponseEntity.status(400).body(new JsonResponse("Invalid input", "Phone number cannot be empty"));
}

Phone phone = new Phone(request.getNumber(), clientId);

Phone savedPhone = phoneRepository.save(phone);
return ResponseEntity.status(201).body(savedPhone);
}

@DeleteMapping("/{clientId}")
public ResponseEntity<?> deleteClient(@PathVariable Long clientId) {
Optional<Client> client = clientRepository.findById(clientId);
if (client.isEmpty()) {
JsonResponse error = new JsonResponse("Invalid input", "Client not found");
return ResponseEntity.status(404).body(error);
}

clientRepository.deleteById(clientId);
return ResponseEntity.status(201).body(new JsonResponse("Client deleted", "Client Deleted"));
}

@PutMapping("/{clientId}/{field}")
public ResponseEntity<?> editClient(
@PathVariable Long clientId, @PathVariable String field, @RequestBody RequestEditClient request) {
Optional<Client> clientOpt = clientRepository.findById(clientId);
if (clientOpt.isEmpty()) {
JsonResponse error = new JsonResponse("Invalid input", "Client not found");
return ResponseEntity.status(404).body(error);
}

Client client = clientOpt.get();

if (field.equals("name")) {
client.setName(request.getValue());
clientRepository.save(client);
return ResponseEntity.status(201).body(new JsonResponse("Client name updated", "Client name updated"));
}

if (field.equals("address")) {
Optional<Address> addressOpt =
addressRepository.findById(client.getAddress().getId());
if (addressOpt.isEmpty()) {
return ResponseEntity.status(404)
.body(new JsonResponse(
"Address not found",
"Address with ID: " + client.getAddress().getId() + " not found"));
}
Address address = addressOpt.get();
address.setAddress(request.getValue());
Address updatedAddress = addressRepository.save(address);
return ResponseEntity.status(201).body(new JsonResponse("Address updated", "Address updated"));
}
return ResponseEntity.status(400).body(new JsonResponse("bad Request", "Bad request"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ru.otus.controller;

public class JsonResponse {
private String message;
private String details;

public JsonResponse(String message, String details) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

строго говорят, в этом имени Json мало, что значит. Т.е. сериализация с этим классом никак явно не связана.

this.message = message;
this.details = details;
}

public String getMessage() {
return message;
}

public String getDetails() {
return details;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ru.otus.controller;

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 ru.otus.model.User;
import ru.otus.repository.UserRepository;

@Controller
public class UsersController {

private final UserRepository userRepository;

@Autowired
public UsersController(UserRepository userRepository) {
this.userRepository = userRepository;
}

@GetMapping("/users")
public String users(Model model) {
Iterable<User> users = userRepository.findAll();
model.addAttribute("users", users);

model.addAttribute("message", "helloWorld");

return "users";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package ru.otus.controller;

import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ru.otus.model.RequestCreateUser;
import ru.otus.model.User;
import ru.otus.repository.UserRepository;

@RestController
@RequestMapping("/api/users")
public class UsersRestController {

private final UserRepository userRepository;

@Autowired
public UsersRestController(UserRepository userRepository) {
this.userRepository = userRepository;
}

@GetMapping("/{id}")
public ResponseEntity<?> getUserById(@PathVariable Long id) {
Optional<User> user = userRepository.findById(id);
if (user.isEmpty()) {
JsonResponse error = new JsonResponse("User not found", "No user exists with ID: " + id);
return ResponseEntity.status(404).body(error);
}

return ResponseEntity.ok(user.orElse(null));
}

@PostMapping
public ResponseEntity<?> createUser(@RequestBody RequestCreateUser request) {
if (request.getName() == null || request.getName().trim().isEmpty()) {
JsonResponse error = new JsonResponse("Invalid input", "User name cannot be empty");
return ResponseEntity.status(400).body(error); // 400 Bad Request
}

User user = new User();
user.setName(request.getName());
user.setLogin(request.getLogin());
user.setPassword(request.getPassword());
User savedUser = userRepository.save(user);

return ResponseEntity.status(201).body(savedUser);
}
}
25 changes: 25 additions & 0 deletions L28-springDataJdbc/src/main/java/ru/otus/model/Address.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ru.otus.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;

@Getter
@Setter

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

можно использовать record-ы

@NoArgsConstructor
@Table("addresses")
public class Address {
@Id
@Column("id")
private Long id;

@Column("address")
private String address;

public Address(String address) {
this.address = address;
}
}
Loading