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