diff --git a/spring-transaction/pom.xml b/spring-transaction/pom.xml new file mode 100644 index 0000000..3bf6a95 --- /dev/null +++ b/spring-transaction/pom.xml @@ -0,0 +1,57 @@ + + + + spring-boot-transaction + dev.struchkov.example + 0.0.1-SNAPSHOT + + 4.0.0 + + spring-transaction + + + 17 + 17 + + + + + + org.springframework.boot + spring-boot-dependencies + 2.7.2 + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/spring-transaction/rest/person-requests.http b/spring-transaction/rest/person-requests.http new file mode 100644 index 0000000..a7d7159 --- /dev/null +++ b/spring-transaction/rest/person-requests.http @@ -0,0 +1,11 @@ +### Смотрим на первого пользователя +GET http://localhost:8080/api/person/1 +Accept: application/json + +### Смотрим на второго пользователя +GET http://localhost:8080/api/person/2 +Accept: application/json + +### Смотрим на третьего пользователя +GET http://localhost:8080/api/person/3 +Accept: application/json \ No newline at end of file diff --git a/spring-transaction/rest/transaction-money-requests.http b/spring-transaction/rest/transaction-money-requests.http new file mode 100644 index 0000000..7fb0934 --- /dev/null +++ b/spring-transaction/rest/transaction-money-requests.http @@ -0,0 +1,9 @@ +### Отправляем деньги от первого пользователя втором +POST http://localhost:8080/api/money/send +Content-Type: application/json + +{ + "personFrom": 1, + "personTo": 2, + "amount": 100 +} \ No newline at end of file diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/Application.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/Application.java new file mode 100644 index 0000000..b1520dc --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/Application.java @@ -0,0 +1,13 @@ +package dev.struchkov.example.transaction; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/controller/PersonController.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/controller/PersonController.java new file mode 100644 index 0000000..46b9acf --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/controller/PersonController.java @@ -0,0 +1,25 @@ +package dev.struchkov.example.transaction.controller; + +import dev.struchkov.example.transaction.domain.Person; +import dev.struchkov.example.transaction.repository.PersonRepository; +import lombok.RequiredArgsConstructor; +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.RestController; + +import java.util.Optional; + +@RestController +@RequestMapping("/api/person") +@RequiredArgsConstructor +public class PersonController { + + private final PersonRepository personRepository; + + @GetMapping("{id}") + public Optional getById(@PathVariable Long id) { + return personRepository.findById(id); + } + +} diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/controller/TransactionMoneyController.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/controller/TransactionMoneyController.java new file mode 100644 index 0000000..66d7c87 --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/controller/TransactionMoneyController.java @@ -0,0 +1,29 @@ +package dev.struchkov.example.transaction.controller; + +import dev.struchkov.example.transaction.dto.TransactionDto; +import dev.struchkov.example.transaction.service.TransactionMoneyService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("api/money") +@RequiredArgsConstructor +public class TransactionMoneyController { + + private final TransactionMoneyService service; + + @PostMapping("send") + public HttpStatus sendMoney(@RequestBody TransactionDto transactionDto) { + service.sendMoney( + transactionDto.getPersonFrom(), + transactionDto.getPersonTo(), + transactionDto.getAmount() + ); + return HttpStatus.OK; + } + +} diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/domain/Person.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/domain/Person.java new file mode 100644 index 0000000..1c04324 --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/domain/Person.java @@ -0,0 +1,29 @@ +package dev.struchkov.example.transaction.domain; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Getter +@Setter +@Table(name = "person") +public class Person { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "name") + private String name; + + @Column(name = "balance") + private Long balance; + +} diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/domain/TransactionMoney.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/domain/TransactionMoney.java new file mode 100644 index 0000000..4479b0a --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/domain/TransactionMoney.java @@ -0,0 +1,36 @@ +package dev.struchkov.example.transaction.domain; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Getter +@Setter +@Table(name = "transaction") +public class TransactionMoney { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "person_from") + private Person personFrom; + + @ManyToOne + @JoinColumn(name = "person_to") + private Person personTo; + + @Column(name = "amount") + private Long amount; + +} diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/dto/TransactionDto.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/dto/TransactionDto.java new file mode 100644 index 0000000..edfd7c5 --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/dto/TransactionDto.java @@ -0,0 +1,14 @@ +package dev.struchkov.example.transaction.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class TransactionDto { + + private Long personFrom; + private Long personTo; + private Long amount; + +} diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/repository/PersonRepository.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/repository/PersonRepository.java new file mode 100644 index 0000000..485046f --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/repository/PersonRepository.java @@ -0,0 +1,16 @@ +package dev.struchkov.example.transaction.repository; + +import dev.struchkov.example.transaction.domain.Person; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface PersonRepository extends JpaRepository { + + @Query(nativeQuery = true, value = "SELECT person.balance FROM person WHERE id = :id") + Long getBalance(@Param("id") Long id); + + @Query("SELECT p.balance FROM Person p WHERE p.id = :id") + Long getBalanceJpql(@Param("id") Long id); + +} diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/repository/TransactionMoneyRepository.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/repository/TransactionMoneyRepository.java new file mode 100644 index 0000000..1ae239b --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/repository/TransactionMoneyRepository.java @@ -0,0 +1,7 @@ +package dev.struchkov.example.transaction.repository; + +import dev.struchkov.example.transaction.domain.TransactionMoney; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TransactionMoneyRepository extends JpaRepository { +} diff --git a/spring-transaction/src/main/java/dev/struchkov/example/transaction/service/TransactionMoneyService.java b/spring-transaction/src/main/java/dev/struchkov/example/transaction/service/TransactionMoneyService.java new file mode 100644 index 0000000..1eb465c --- /dev/null +++ b/spring-transaction/src/main/java/dev/struchkov/example/transaction/service/TransactionMoneyService.java @@ -0,0 +1,38 @@ +package dev.struchkov.example.transaction.service; + +import dev.struchkov.example.transaction.domain.Person; +import dev.struchkov.example.transaction.domain.TransactionMoney; +import dev.struchkov.example.transaction.repository.PersonRepository; +import dev.struchkov.example.transaction.repository.TransactionMoneyRepository; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class TransactionMoneyService { + + private final TransactionMoneyRepository transactionMoneyRepository; + private final PersonRepository personRepository; + + @Transactional + public void sendMoney(@NonNull Long personFromId, @NonNull Long personToId, @NonNull Long amount) { + final Person personFrom = personRepository.findById(personFromId).orElseThrow(); + final Person personTo = personRepository.findById(personToId).orElseThrow(); + + final TransactionMoney transactionMoney = new TransactionMoney(); + transactionMoney.setPersonTo(personTo); + transactionMoney.setPersonFrom(personFrom); + transactionMoney.setAmount(amount); + + transactionMoneyRepository.save(transactionMoney); + personFrom.setBalance(personFrom.getBalance() - amount); + personTo.setBalance(personTo.getBalance() + amount); + } + + public void surprise() { + throw new RuntimeException("Сюрприиииз"); + } + +} diff --git a/spring-transaction/src/main/resources/application.yml b/spring-transaction/src/main/resources/application.yml new file mode 100644 index 0000000..3bce5ea --- /dev/null +++ b/spring-transaction/src/main/resources/application.yml @@ -0,0 +1,15 @@ +spring: + datasource: + password: 121314Ma + username: postgres + url: jdbc:postgresql://localhost:5432/test + driver-class-name: org.postgresql.Driver + + jpa: + properties: + hibernate: + format_sql: true +logging: + level: + org.springframework.orm.jpa: DEBUG + org.springframework.transaction: DEBUG \ No newline at end of file diff --git a/spring-transaction/src/main/resources/logback.xml b/spring-transaction/src/main/resources/logback.xml new file mode 100644 index 0000000..86db7c9 --- /dev/null +++ b/spring-transaction/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + \ No newline at end of file