From 56a1466347648b72af912dc4e56675b73a56dc4c Mon Sep 17 00:00:00 2001 From: Alexander Kim Date: Wed, 2 Apr 2025 16:54:29 +0300 Subject: [PATCH 1/4] feat: implement lab2 --- .gitignore | 2 + Application/pom.xml | 13 + .../Repositories/IBankAccountRepository.java | 44 ---- .../Repositories/IOperationRepository.java | 29 --- .../Repositories/IUserRepository.java | 44 ---- .../Application/Managers/UserManager.java | 57 +++-- .../Application/Models/Entites/Operation.java | 30 --- .../{Entites => Entities}/BankAccount.java | 28 ++- .../Models/Entities/Operation.java | 43 ++++ .../Models/{Entites => Entities}/User.java | 46 ++-- .../Models/Enums/OperationType.java | 1 - .../Application/Models/Utils/IdGenerator.java | 31 --- .../ResultTypes/BankAccountResult.java | 2 +- .../ResultTypes/OperationResult.java | 2 +- .../ResultTypes/UserResult.java | 2 +- .../Application/Services/UserService.java | 228 ------------------ DataAccess/pom.xml | 55 +++++ .../DataAccess/BankAccountRepository.java | 99 -------- .../java/DataAccess/OperationRepository.java | 50 ---- .../main/java/DataAccess/UserRepository.java | 94 -------- .../main/java/Presentation/Console/Menu.java | 197 ++++++++------- .../Interfaces/IUserController.java | 64 +++-- Presentation/src/test/java/BankTests.java | 86 +++---- pom.xml | 48 ++++ 24 files changed, 425 insertions(+), 870 deletions(-) delete mode 100644 Application/src/main/java/Application/Abstractions/Repositories/IBankAccountRepository.java delete mode 100644 Application/src/main/java/Application/Abstractions/Repositories/IOperationRepository.java delete mode 100644 Application/src/main/java/Application/Abstractions/Repositories/IUserRepository.java delete mode 100644 Application/src/main/java/Application/Models/Entites/Operation.java rename Application/src/main/java/Application/Models/{Entites => Entities}/BankAccount.java (60%) create mode 100644 Application/src/main/java/Application/Models/Entities/Operation.java rename Application/src/main/java/Application/Models/{Entites => Entities}/User.java (56%) delete mode 100644 Application/src/main/java/Application/Models/Utils/IdGenerator.java rename Application/src/main/java/Application/{Contracts => }/ResultTypes/BankAccountResult.java (96%) rename Application/src/main/java/Application/{Contracts => }/ResultTypes/OperationResult.java (94%) rename Application/src/main/java/Application/{Contracts => }/ResultTypes/UserResult.java (96%) delete mode 100644 Application/src/main/java/Application/Services/UserService.java delete mode 100644 DataAccess/src/main/java/DataAccess/BankAccountRepository.java delete mode 100644 DataAccess/src/main/java/DataAccess/OperationRepository.java delete mode 100644 DataAccess/src/main/java/DataAccess/UserRepository.java rename Application/src/main/java/Application/Contracts/Interfaces/IUserService.java => Presentation/src/main/java/Presentation/Interfaces/IUserController.java (59%) diff --git a/.gitignore b/.gitignore index 277d995..343d1cc 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,8 @@ bin/ /dist/ /nbdist/ /.nb-gradle/ +DataAccess.iml +Presentation.iml ### VS Code ### .vscode/ diff --git a/Application/pom.xml b/Application/pom.xml index c8522ac..bf8075d 100644 --- a/Application/pom.xml +++ b/Application/pom.xml @@ -24,6 +24,19 @@ provided + + org.postgresql + postgresql + 42.7.2 + runtime + + + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + + diff --git a/Application/src/main/java/Application/Abstractions/Repositories/IBankAccountRepository.java b/Application/src/main/java/Application/Abstractions/Repositories/IBankAccountRepository.java deleted file mode 100644 index fe7c508..0000000 --- a/Application/src/main/java/Application/Abstractions/Repositories/IBankAccountRepository.java +++ /dev/null @@ -1,44 +0,0 @@ -package Application.Abstractions.Repositories; - -import Application.Contracts.ResultTypes.BankAccountResult; -import Application.Models.Entites.BankAccount; - -/** - * Репозиторий для управления банковскими счетами. - * Реализует паттерн CRUD для добавления, поиска, обновления и удаления банковских счетов. - */ -public interface IBankAccountRepository { - - /** - * Добавляет новый банковский счет в хранилище данных. - * - * @param account объект банковского счета, который необходимо добавить. - * @return результат операции добавления банковского счета, может содержать сообщение об ошибке или подтверждение успеха. - */ - BankAccountResult AddBankAccount(BankAccount account); - - /** - * Ищет банковский счет в хранилище данных по его идентификатору. - * - * @param id идентификатор банковского счета, который нужно найти. - * @return объект банковского счета, если он существует; {@code null}, если счет не найден. - */ - BankAccount FindBankAccountById(Integer id); - - /** - * Обновляет баланс существующего банковского счета. - * - * @param id идентификатор банковского счета, баланс которого необходимо обновить. - * @param balance новый баланс банковского счета. - * @return результат операции обновления баланса, может содержать сообщение об ошибке или подтверждение успеха. - */ - BankAccountResult UpdateBankAccountBalance(Integer id, Double balance); - - /** - * Удаляет банковский счет из хранилища данных по его идентификатору. - * - * @param id идентификатор банковского счета, который нужно удалить. - * @return результат операции удаления банковского счета, может содержать сообщение об ошибке или подтверждение успеха. - */ - BankAccountResult DeleteBankAccount(Integer id); -} diff --git a/Application/src/main/java/Application/Abstractions/Repositories/IOperationRepository.java b/Application/src/main/java/Application/Abstractions/Repositories/IOperationRepository.java deleted file mode 100644 index 2829ae3..0000000 --- a/Application/src/main/java/Application/Abstractions/Repositories/IOperationRepository.java +++ /dev/null @@ -1,29 +0,0 @@ -package Application.Abstractions.Repositories; - -import Application.Contracts.ResultTypes.OperationResult; -import Application.Models.Entites.Operation; - -import java.util.ArrayList; - -/** - * Репозиторий для управления операциями с банковскими счетами. - * Реализует паттерн CRUD для добавления операций и получения истории операций. - */ -public interface IOperationRepository { - - /** - * Добавляет новую операцию в хранилище данных. - * - * @param operation операция, которую необходимо добавить в хранилище. - * @return результат операции добавления, может содержать сообщение об ошибке или подтверждение успеха. - */ - OperationResult AddOperation(Operation operation); - - /** - * Извлекает историю операций для конкретного банковского счета. - * - * @param bankAccountId идентификатор банковского счета, для которого нужно получить историю операций. - * @return список операций, выполненных с указанным банковским счетом. - */ - ArrayList GetOperationHistory(Integer bankAccountId); -} diff --git a/Application/src/main/java/Application/Abstractions/Repositories/IUserRepository.java b/Application/src/main/java/Application/Abstractions/Repositories/IUserRepository.java deleted file mode 100644 index 14a89cc..0000000 --- a/Application/src/main/java/Application/Abstractions/Repositories/IUserRepository.java +++ /dev/null @@ -1,44 +0,0 @@ -package Application.Abstractions.Repositories; - -import Application.Contracts.ResultTypes.UserResult; -import Application.Models.Entites.User; - -/** - * Репозиторий для управления операциями с пользователями. - * Использует паттерн CRUD (Create, Read, Update, Delete) для добавления, поиска, обновления и удаления пользователей. - */ -public interface IUserRepository { - - /** - * Добавляет нового пользователя в хранилище данных. - * - * @param user объект пользователя, который необходимо добавить. - * @return результат операции добавления пользователя, может содержать сообщение об ошибке или подтверждение успеха. - */ - UserResult AddUser(User user); - - /** - * Ищет пользователя в хранилище данных по его идентификатору. - * - * @param id идентификатор пользователя, которого нужно найти. - * @return найденный объект пользователя, если он существует; {@code null}, если пользователь не найден. - */ - User FindUserById(Integer id); - - /** - * Обновляет информацию о существующем пользователе в хранилище данных. - * - * @param id идентификатор пользователя, чьи данные нужно обновить. - * @param userUpdate объект с обновленными данными пользователя. - * @return результат операции обновления пользователя, может содержать сообщение об ошибке или подтверждение успеха. - */ - UserResult UpdateUser(Integer id, User userUpdate); - - /** - * Удаляет пользователя из хранилища данных по его идентификатору. - * - * @param id идентификатор пользователя, которого нужно удалить. - * @return результат операции удаления пользователя, может содержать сообщение об ошибке или подтверждение успеха. - */ - UserResult DeleteUser(Integer id); -} diff --git a/Application/src/main/java/Application/Managers/UserManager.java b/Application/src/main/java/Application/Managers/UserManager.java index b20b400..ec4f438 100644 --- a/Application/src/main/java/Application/Managers/UserManager.java +++ b/Application/src/main/java/Application/Managers/UserManager.java @@ -1,18 +1,19 @@ package Application.Managers; -import Application.Contracts.ResultTypes.OperationResult; -import Application.Models.Entites.BankAccount; -import Application.Models.Entites.Operation; -import Application.Models.Entites.User; +import Application.ResultTypes.OperationResult; +import Application.Models.Entities.BankAccount; +import Application.Models.Entities.Operation; +import Application.Models.Entities.User; import java.util.ArrayList; +import java.util.List; /** * Класс-менеджер для управления данными пользователей, их банковскими счетами и друзьями. * Предоставляет методы для получения информации о пользователе, добавления/удаления друзей, * управления банковскими счетами и вывода истории операций. */ -public record UserManager() { +public class UserManager { /** * Выводит информацию о пользователе, включая его данные и банковские счета. @@ -20,36 +21,42 @@ public record UserManager() { * @param user объект пользователя, информацию о котором нужно вывести. */ public void GetUserInfo(User user) { + if (user == null) { - System.out.println("User data is not available."); + System.out.println("Пользователь с ID " + user.getId() + " не найден."); return; } - System.out.println("User Information:"); - System.out.println("──────────────────────────────────"); - System.out.printf("ID: %d%n", user.getId()); - System.out.printf("Login: %s%n", user.getLogin()); - System.out.printf("Name: %s%n", user.getName()); - System.out.printf("Age: %d%n", user.getAge()); - System.out.printf("Sex: %s%n", user.getSex()); - System.out.printf("Hair Color: %s%n", user.getHairType()); +// // Инициализация ленивых коллекций +// Hibernate.initialize(user.getBankAccounts()); +// Hibernate.initialize(user.getFriends()); + + System.out.println("ID: " + user.getId()); + System.out.println("Логин: " + user.getLogin()); + System.out.println("Имя: " + user.getName()); + System.out.println("Возраст: " + user.getAge()); + System.out.println("Пол: " + user.getSex()); + System.out.println("Цвет волос: " + user.getHairType()); - System.out.println("\nBank Accounts:"); + // Вывод банковских счетов + System.out.println("\nБанковские счета:"); if (user.getBankAccounts().isEmpty()) { - System.out.println("No bank accounts available."); + System.out.println("Нет привязанных счетов."); } else { - user.getBankAccounts().forEach(account -> System.out.printf("Account ID: %d%n", account)); + for (BankAccount account : user.getBankAccounts()) { + System.out.println("ID счета: " + account.getId() + ", Баланс: " + account.getBalance()); + } } - System.out.println("\nFriends:"); + // Вывод друзей + System.out.println("\nДрузья:"); if (user.getFriends().isEmpty()) { - System.out.println("No friends available."); + System.out.println("Нет друзей."); } else { - user.getFriends().forEach(friend -> - System.out.printf("Friend ID: %d | Name: %s%n", friend.getId(), friend.getName())); + for (User friend : user.getFriends()) { + System.out.println("ID друга: " + friend.getId() + ", Имя: " + friend.getName()); + } } - - System.out.println("──────────────────────────────────\n"); } /** @@ -81,7 +88,7 @@ public void RemoveFriend(User user, User other) { * @param bankAccount банковский счет для добавления. */ public void AddBankAccount(User user, BankAccount bankAccount) { - user.getBankAccounts().add(bankAccount.getId()); + user.getBankAccounts().add(bankAccount); } /** @@ -113,7 +120,7 @@ public void CheckBalance(User user, BankAccount bankAccount) { * @param operations список операций, связанных с этим счетом. * @return результат операции (успех или ошибка). */ - public OperationResult PrintHistory(BankAccount account, ArrayList operations) { + public OperationResult PrintHistory(BankAccount account, List operations) { if (operations == null) { return new OperationResult.OperationError("Operations can not be null."); } else { diff --git a/Application/src/main/java/Application/Models/Entites/Operation.java b/Application/src/main/java/Application/Models/Entites/Operation.java deleted file mode 100644 index 2b2ee00..0000000 --- a/Application/src/main/java/Application/Models/Entites/Operation.java +++ /dev/null @@ -1,30 +0,0 @@ -package Application.Models.Entites; - -import lombok.Getter; -import Application.Models.Enums.OperationType; - -/** - * Класс, представляющий операцию с банковским счетом. - * Хранит информацию о типе операции, сумме и счете, на котором она была проведена. - */ -@Getter -public class Operation { - private final Integer BankAccountId; - - private final OperationType Type; - - private final Double Amount; - - /** - * Конструктор для создания новой операции. - * - * @param bankAccountId идентификатор банковского счета, на котором выполнена операция. - * @param type тип операции (например, депозит или снятие). - * @param amount сумма, участвующая в операции. - */ - public Operation(Integer bankAccountId, OperationType type, Double amount) { - this.BankAccountId = bankAccountId; - this.Type = type; - this.Amount = amount; - } -} diff --git a/Application/src/main/java/Application/Models/Entites/BankAccount.java b/Application/src/main/java/Application/Models/Entities/BankAccount.java similarity index 60% rename from Application/src/main/java/Application/Models/Entites/BankAccount.java rename to Application/src/main/java/Application/Models/Entities/BankAccount.java index 029f47e..7fd15b4 100644 --- a/Application/src/main/java/Application/Models/Entites/BankAccount.java +++ b/Application/src/main/java/Application/Models/Entities/BankAccount.java @@ -1,35 +1,41 @@ -package Application.Models.Entites; +package Application.Models.Entities; -import lombok.Getter; -import lombok.Setter; -import Application.Models.Utils.IdGenerator; +import jakarta.persistence.*; +import lombok.*; /** * Класс, представляющий банковский счет пользователя. * Хранит информацию о счете, балансе и привязанном пользователе. */ +@Entity +@Table(name = "BankAccounts") @Getter +@NoArgsConstructor public class BankAccount { - final private Integer id; + @Id + @Setter + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; @Setter private Double balance; - private final String userLogin; + @Column(name = "userLogin") + private String userLogin; - private final Integer UserId; + @ManyToOne + @JoinColumn(name = "userId", nullable = false) + private User user; /** * Конструктор для создания нового банковского счета. * Генерирует уникальный идентификатор счета и связывает его с пользователем. * - * @param idGenerator генератор ID для создания уникального идентификатора счета. * @param user пользователь, к которому будет привязан новый счет. */ - public BankAccount(IdGenerator idGenerator, User user) { - this.id = idGenerator.generateBankAccountId(); + public BankAccount(User user) { this.balance = 0.0; this.userLogin = user.getLogin(); - this.UserId = user.getId(); + this.user = user; } } diff --git a/Application/src/main/java/Application/Models/Entities/Operation.java b/Application/src/main/java/Application/Models/Entities/Operation.java new file mode 100644 index 0000000..9a7664e --- /dev/null +++ b/Application/src/main/java/Application/Models/Entities/Operation.java @@ -0,0 +1,43 @@ +package Application.Models.Entities; + +import jakarta.persistence.*; +import lombok.*; +import Application.Models.Enums.OperationType; + +/** + * Класс, представляющий операцию с банковским счетом. + * Хранит информацию о типе операции, сумме и счете, на котором она была проведена. + */ +@Getter +@Setter +@NoArgsConstructor +@Entity +@Table(name = "Operations") +public class Operation { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @ManyToOne + @JoinColumn(name = "accountId", nullable = false) + private BankAccount bankAccount; + + @Column(nullable = false) + private Double amount; + + @Column(nullable = false) + private String type; + + /** + * Конструктор для создания новой операции. + * + * @param bankAccount банковский счет, на котором выполнена операция. + * @param type тип операции (например, депозит или снятие). + * @param amount сумма, участвующая в операции. + */ + public Operation(BankAccount bankAccount, OperationType type, Double amount) { + this.bankAccount = bankAccount; + this.type = type.toString(); + this.amount = amount; + } +} diff --git a/Application/src/main/java/Application/Models/Entites/User.java b/Application/src/main/java/Application/Models/Entities/User.java similarity index 56% rename from Application/src/main/java/Application/Models/Entites/User.java rename to Application/src/main/java/Application/Models/Entities/User.java index dc44a2d..dffba50 100644 --- a/Application/src/main/java/Application/Models/Entites/User.java +++ b/Application/src/main/java/Application/Models/Entities/User.java @@ -1,61 +1,69 @@ -package Application.Models.Entites; +package Application.Models.Entities; +import jakarta.persistence.*; import lombok.*; import Application.Models.Enums.HairColor; import Application.Models.Enums.Sex; -import Application.Models.Utils.IdGenerator; - -import java.util.ArrayList; +import java.util.*; /** * Класс, представляющий пользователя системы. * Хранит информацию о пользователе, включая личные данные, список банковских счетов и друзей. */ +@Entity @Getter -@Setter +@Table(name = "Users") +@NoArgsConstructor public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; + @Column(nullable = false, unique = true) private String login; + @Column(nullable = false) private String name; + @Column(nullable = false) private Integer age; + @Enumerated(EnumType.STRING) private Sex sex; + @Enumerated(EnumType.STRING) + @Column(name = "hairColor") private HairColor hairType; - private ArrayList bankAccounts = new ArrayList<>(); + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private List bankAccounts; - private ArrayList friends = new ArrayList<>(); + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable( + name = "Friends", + joinColumns = @JoinColumn(name = "userId"), + inverseJoinColumns = @JoinColumn(name = "friendId") + ) + private List friends; /** * Конструктор для создания нового пользователя. * Генерирует уникальный идентификатор для пользователя и инициализирует его данные. * - * @param idGenerator генератор ID для создания уникального идентификатора пользователя. * @param login логин пользователя. * @param name имя пользователя. * @param age возраст пользователя. * @param sex пол пользователя. * @param hairType цвет волос пользователя. */ - public User( - IdGenerator idGenerator, - String login, - String name, - Integer age, - Sex sex, - HairColor hairType - ) { - this.id = idGenerator.generateUserId(); + public User(String login, String name, Integer age, Sex sex, HairColor hairType) { this.login = login; this.name = name; this.age = age; this.sex = sex; this.hairType = hairType; - this.bankAccounts = bankAccounts != null ? bankAccounts : new ArrayList<>(); - this.friends = friends != null ? friends : new ArrayList<>(); + this.bankAccounts = new ArrayList<>(); + this.friends = new ArrayList<>(); } } + diff --git a/Application/src/main/java/Application/Models/Enums/OperationType.java b/Application/src/main/java/Application/Models/Enums/OperationType.java index a11cee8..fba1823 100644 --- a/Application/src/main/java/Application/Models/Enums/OperationType.java +++ b/Application/src/main/java/Application/Models/Enums/OperationType.java @@ -7,5 +7,4 @@ public enum OperationType { Deposit, Withdraw, Transfer, - CheckBalance } diff --git a/Application/src/main/java/Application/Models/Utils/IdGenerator.java b/Application/src/main/java/Application/Models/Utils/IdGenerator.java deleted file mode 100644 index e461b94..0000000 --- a/Application/src/main/java/Application/Models/Utils/IdGenerator.java +++ /dev/null @@ -1,31 +0,0 @@ -package Application.Models.Utils; - -/** - * Класс для генерации уникальных Id пользователей и банковских счетов - */ -public class IdGenerator { - private int userId = 0; - private int bankAccountId = 0; - - /** - * Генерирует уникальный идентификатор пользователя. - * Каждый вызов метода увеличивает текущий userId на 1 и возвращает новое значение. - * Метод синхронизирован для обеспечения корректности работы в многозадачной среде. - * - * @return новый уникальный идентификатор пользователя. - */ - public synchronized int generateUserId() { - return ++userId; - } - - /** - * Генерирует уникальный идентификатор банковского счета. - * Каждый вызов метода увеличивает текущий bankAccountId на 1 и возвращает новое значение. - * Метод синхронизирован для обеспечения корректности работы в многозадачной среде. - * - * @return новый уникальный идентификатор банковского счета. - */ - public synchronized int generateBankAccountId() { - return ++bankAccountId; - } -} diff --git a/Application/src/main/java/Application/Contracts/ResultTypes/BankAccountResult.java b/Application/src/main/java/Application/ResultTypes/BankAccountResult.java similarity index 96% rename from Application/src/main/java/Application/Contracts/ResultTypes/BankAccountResult.java rename to Application/src/main/java/Application/ResultTypes/BankAccountResult.java index 16f9318..321b999 100644 --- a/Application/src/main/java/Application/Contracts/ResultTypes/BankAccountResult.java +++ b/Application/src/main/java/Application/ResultTypes/BankAccountResult.java @@ -1,4 +1,4 @@ -package Application.Contracts.ResultTypes; +package Application.ResultTypes; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/Application/src/main/java/Application/Contracts/ResultTypes/OperationResult.java b/Application/src/main/java/Application/ResultTypes/OperationResult.java similarity index 94% rename from Application/src/main/java/Application/Contracts/ResultTypes/OperationResult.java rename to Application/src/main/java/Application/ResultTypes/OperationResult.java index 0adb251..c834d01 100644 --- a/Application/src/main/java/Application/Contracts/ResultTypes/OperationResult.java +++ b/Application/src/main/java/Application/ResultTypes/OperationResult.java @@ -1,4 +1,4 @@ -package Application.Contracts.ResultTypes; +package Application.ResultTypes; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/Application/src/main/java/Application/Contracts/ResultTypes/UserResult.java b/Application/src/main/java/Application/ResultTypes/UserResult.java similarity index 96% rename from Application/src/main/java/Application/Contracts/ResultTypes/UserResult.java rename to Application/src/main/java/Application/ResultTypes/UserResult.java index 87b9595..95355bd 100644 --- a/Application/src/main/java/Application/Contracts/ResultTypes/UserResult.java +++ b/Application/src/main/java/Application/ResultTypes/UserResult.java @@ -1,4 +1,4 @@ -package Application.Contracts.ResultTypes; +package Application.ResultTypes; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/Application/src/main/java/Application/Services/UserService.java b/Application/src/main/java/Application/Services/UserService.java deleted file mode 100644 index 282a16d..0000000 --- a/Application/src/main/java/Application/Services/UserService.java +++ /dev/null @@ -1,228 +0,0 @@ -package Application.Services; - -import lombok.AllArgsConstructor; -import Application.Abstractions.Repositories.IBankAccountRepository; -import Application.Abstractions.Repositories.IOperationRepository; -import Application.Abstractions.Repositories.IUserRepository; -import Application.Contracts.Interfaces.IUserService; -import Application.Contracts.ResultTypes.BankAccountResult; -import Application.Contracts.ResultTypes.OperationResult; -import Application.Contracts.ResultTypes.UserResult; -import Application.Managers.UserManager; -import Application.Models.Entites.BankAccount; -import Application.Models.Entites.Operation; -import Application.Models.Entites.User; -import Application.Models.Enums.OperationType; -import lombok.Getter; - -/** - * Сервис для управления пользователями, их банковскими счетами и операциями. - * Взаимодействует с репозиториями пользователей, банковских счетов и операций. - * Обрабатывает запросы, такие как создание/удаление пользователей, переводы, операции с балансом и так далее. - */ -@AllArgsConstructor -public class UserService implements IUserService { - - @Getter - private IUserRepository _userRepository; - - @Getter - private IBankAccountRepository _bankAccountRepository; - - @Getter - private IOperationRepository _operationRepository; - - private UserManager _userManager; - - /** - * Создает нового пользователя. - * - * @param user объект пользователя, который нужно добавить. - * @return result-type добавления пользователя. - */ - @Override - public UserResult CreateUser(User user) { - return _userRepository.AddUser(user); - } - - /** - * Удаляет существующего пользователя. - * - * @param user объект пользователя, которого нужно удалить. - * @return result-type удаления пользователя. - */ - @Override - public UserResult DeleteUser(User user) { - return _userRepository.DeleteUser(user.getId()); - } - - /** - * Получает информацию о пользователе и выводит ее. - * - * @param user объект пользователя, информацию о котором нужно вывести. - */ - @Override - public void GetUserInfo(User user) { - _userManager.GetUserInfo(user); - } - - /** - * Добавляет другого пользователя в список друзей. - * - * @param user текущий пользователь, добавляющий друга. - * @param other пользователь, который будет добавлен в друзья. - */ - @Override - public void AddFriend(User user, User other) { - _userManager.AddFriend(user, other); - } - - /** - * Удаляет пользователя из списка друзей. - * - * @param user текущий пользователь, удаляющий друга. - * @param other пользователь, которого нужно удалить из друзей. - */ - @Override - public void RemoveFriend(User user, User other) { - _userManager.RemoveFriend(user, other); - } - - /** - * Добавляет новый банковский счет пользователю. - * - * @param user пользователь, которому добавляется банковский счет. - * @param bankAccount объект банковского счета, который нужно добавить. - * @return result-type добавления счета. - */ - @Override - public BankAccountResult addBankAccount(User user, BankAccount bankAccount) { - _userManager.AddBankAccount(user, bankAccount); - return _bankAccountRepository.AddBankAccount(bankAccount); - } - - /** - * Удаляет банковский счет у пользователя. - * - * @param user пользователь, у которого нужно удалить банковский счет. - * @param bankAccount объект банковского счета, который нужно удалить. - * @return result-type удаления счета. - */ - @Override - public BankAccountResult RemoveBankAccount(User user, BankAccount bankAccount) { - _userManager.RemoveBankAccount(user, bankAccount); - return _bankAccountRepository.DeleteBankAccount(bankAccount.getId()); - } - - /** - * Проверяет баланс на банковском счете пользователя. - * - * @param user пользователь, чьи средства нужно проверить. - * @param bankAccount объект банковского счета, на котором нужно проверить баланс. - * @return result-type операции (успех или ошибка). - */ - @Override - public OperationResult CheckBalance(User user, BankAccount bankAccount) { - _userManager.CheckBalance(user, bankAccount); - return _operationRepository.AddOperation(new Operation(bankAccount.getId(), OperationType.CheckBalance, 0.0)); - } - - /** - * Пополняет банковский счет на указанную сумму. - * - * @param bankAccount объект банковского счета, на который нужно пополнить средства. - * @param amount сумма пополнения. - * @return result-type операции (успех или ошибка). - */ - @Override - public OperationResult Deposit(BankAccount bankAccount, Double amount) { - var account = _bankAccountRepository.FindBankAccountById(bankAccount.getId()); - _bankAccountRepository.UpdateBankAccountBalance(account.getId(), account.getBalance() + amount); - return _operationRepository.AddOperation(new Operation(bankAccount.getId(), OperationType.Deposit, amount)); - } - - /** - * Снимает средства с банковского счета. - * - * @param bankAccount объект банковского счета, с которого нужно снять деньги. - * @param amount сумма снятия. - * @return result-type операции (успех или ошибка). - */ - @Override - public OperationResult Withdraw(BankAccount bankAccount, Double amount) { - var account = _bankAccountRepository.FindBankAccountById(bankAccount.getId()); - if (account.getBalance() - amount >= 0) { - _bankAccountRepository.UpdateBankAccountBalance(account.getId(), account.getBalance() - amount); - return _operationRepository.AddOperation(new Operation(bankAccount.getId(), OperationType.Withdraw, amount)); - } - return new OperationResult.OperationError("Not enough balance"); - } - - /** - * Переводит средства между двумя банковскими счетами. - * В зависимости от типа отношений между пользователями применяется комиссия. - * - * @param bankAccount1 первый банковский счет (откуда переводятся деньги). - * @param bankAccount2 второй банковский счет (куда переводятся деньги). - * @param amount сумма перевода. - * @return result-type операции (успех или ошибка). - */ - @Override - public OperationResult Transfer(BankAccount bankAccount1, BankAccount bankAccount2, Double amount) { - if (amount == null || amount <= 0) { - return new OperationResult.OperationError("Invalid transfer amount."); - } - - var account1 = _bankAccountRepository.FindBankAccountById(bankAccount1.getId()); - var account2 = _bankAccountRepository.FindBankAccountById(bankAccount2.getId()); - - if (account1 == null || account2 == null) { - return new OperationResult.OperationError("One or both bank accounts not found."); - } - - var user1 = _userRepository.FindUserById(account1.getUserId()); - var user2 = _userRepository.FindUserById(account2.getUserId()); - - if (user1 == null || user2 == null) { - return new OperationResult.OperationError("One or both users not found."); - } - - double commissionRate; - - if (account1.getUserId().equals(account2.getUserId())) { - commissionRate = 0.00; - } else if (user1.getFriends().stream().anyMatch(friend -> friend.getId().equals(user2.getId()))) { - commissionRate = 0.03; - } else { - commissionRate = 0.10; - } - - double commission = amount * commissionRate; - double totalAmount = amount + commission; - - if (account1.getBalance() < totalAmount) { - return new OperationResult.OperationError("Insufficient funds, including commission."); - } - - _bankAccountRepository.UpdateBankAccountBalance(account1.getId(), account1.getBalance() - totalAmount); - _bankAccountRepository.UpdateBankAccountBalance(account2.getId(), account2.getBalance() + amount); - - _operationRepository.AddOperation(new Operation(bankAccount1.getId(), OperationType.Transfer, totalAmount)); - _operationRepository.AddOperation(new Operation(bankAccount2.getId(), OperationType.Deposit, amount)); - - return new OperationResult.Success(); - } - - /** - * Получает историю операций по банковскому счету. - * - * @param bankAccount объект банковского счета, для которого нужно получить историю операций. - * @return result-type с выводом историей операций в консоль. - */ - @Override - public OperationResult GetOperationHistory(BankAccount bankAccount) { - var account = _bankAccountRepository.FindBankAccountById(bankAccount.getId()); - var operations = _operationRepository.GetOperationHistory(account.getId()); - return _userManager.PrintHistory(account, operations); - } -} diff --git a/DataAccess/pom.xml b/DataAccess/pom.xml index ec4f99c..bf37e2d 100644 --- a/DataAccess/pom.xml +++ b/DataAccess/pom.xml @@ -29,6 +29,35 @@ Application 1.0-SNAPSHOT + + org.hibernate + hibernate-core + 6.4.4.Final + + + + org.hibernate + hibernate-ehcache + 4.3.0.Beta3 + + + + org.postgresql + postgresql + 42.7.2 + + + + net.bytebuddy + byte-buddy + 1.14.7 + + + + org.flywaydb + flyway-core + 9.22.0 + @@ -119,7 +148,33 @@ + + + org.flywaydb + flyway-maven-plugin + 9.22.0 + + jdbc:postgresql://localhost:5432/JavaLabsDb + postgres + limosha + + classpath:db/migration + + true + + + + + + + src/main/resources + + **/*.xml + **/*.properties + + + \ No newline at end of file diff --git a/DataAccess/src/main/java/DataAccess/BankAccountRepository.java b/DataAccess/src/main/java/DataAccess/BankAccountRepository.java deleted file mode 100644 index c04979e..0000000 --- a/DataAccess/src/main/java/DataAccess/BankAccountRepository.java +++ /dev/null @@ -1,99 +0,0 @@ -package DataAccess; - -import lombok.NoArgsConstructor; -import Application.Abstractions.Repositories.IBankAccountRepository; -import Application.Contracts.ResultTypes.BankAccountResult; -import Application.Models.Entites.BankAccount; - -import java.util.ArrayList; -import java.util.Objects; - -/** - * Репозиторий для управления банковскими счетами. - * Реализует интерфейс {@link IBankAccountRepository} и выполняет CRUD-операции с объектами {@link BankAccount}. - * - *

Хранение банковских счетов осуществляется в памяти с использованием {@link ArrayList}.

- */ -@NoArgsConstructor -public class BankAccountRepository implements IBankAccountRepository { - - /** - * Внутреннее хранилище банковских счетов в памяти. - */ - private final ArrayList _bankAccounts = new ArrayList<>(); - - /** - * Добавляет новый банковский счет в хранилище. - * - * @param account объект банковского счета, который будет добавлен. - * @return {@link BankAccountResult.Success} при успешном добавлении - * или {@link BankAccountResult.BankAccountCreationError} в случае ошибки. - */ - @Override - public BankAccountResult AddBankAccount(BankAccount account) { - if (account == null) { - return new BankAccountResult.BankAccountCreationError("Bank account cannot be null"); - } - _bankAccounts.add(account); - return new BankAccountResult.Success(); - } - - /** - * Ищет банковский счет по идентификатору. - * - * @param id идентификатор банковского счета. - * @return объект {@link BankAccount}, если найден, иначе {@code null}. - */ - @Override - public BankAccount FindBankAccountById(Integer id) { - if (id < 0) { - return null; - } - for (BankAccount account : _bankAccounts) { - if (Objects.equals(account.getId(), id)) { - return account; - } - } - return null; - } - - /** - * Обновляет баланс банковского счета. - * - * @param id идентификатор банковского счета. - * @param balance новый баланс счета. - * @return {@link BankAccountResult.Success} при успешном обновлении - * или {@link BankAccountResult.BankAccountUpdateError} в случае ошибки. - */ - @Override - public BankAccountResult UpdateBankAccountBalance(Integer id, Double balance) { - if (id < 0 || balance < 0) { - return new BankAccountResult.BankAccountUpdateError("Invalid update parameters"); - } - - for (BankAccount account : _bankAccounts) { - if (Objects.equals(account.getId(), id)) { - account.setBalance(balance); - return new BankAccountResult.Success(); - } - } - - return new BankAccountResult.BankAccountUpdateError("Bank account balance update failed"); - } - - /** - * Удаляет банковский счет по идентификатору. - * - * @param id идентификатор банковского счета, который нужно удалить. - * @return {@link BankAccountResult.Success} при успешном удалении - * или {@link BankAccountResult.BankAccountDeletionError} в случае ошибки. - */ - @Override - public BankAccountResult DeleteBankAccount(Integer id) { - if (id < 0) { - return new BankAccountResult.BankAccountDeletionError("Invalid delete parameters"); - } - _bankAccounts.removeIf(bankAccount -> Objects.equals(bankAccount.getId(), id)); - return new BankAccountResult.Success(); - } -} diff --git a/DataAccess/src/main/java/DataAccess/OperationRepository.java b/DataAccess/src/main/java/DataAccess/OperationRepository.java deleted file mode 100644 index 589f474..0000000 --- a/DataAccess/src/main/java/DataAccess/OperationRepository.java +++ /dev/null @@ -1,50 +0,0 @@ -package DataAccess; - -import lombok.NoArgsConstructor; -import Application.Abstractions.Repositories.IOperationRepository; -import Application.Contracts.ResultTypes.OperationResult; -import Application.Models.Entites.Operation; - -import java.util.ArrayList; - -/** - * Репозиторий для управления операциями банковских счетов. - * Реализует интерфейс {@link IOperationRepository} и выполняет операции добавления и получения истории операций. - * - *

Хранение операций осуществляется в памяти с использованием {@link ArrayList}.

- */ -@NoArgsConstructor -public class OperationRepository implements IOperationRepository { - - /** - * Внутреннее хранилище операций в памяти. - */ - private final ArrayList operations = new ArrayList<>(); - - /** - * Добавляет новую операцию в хранилище. - * - * @param operation объект операции, который будет добавлен. - * @return результат операции добавления: {@link OperationResult.Success} при успешном добавлении - * или {@link OperationResult.OperationError} в случае ошибки. - */ - @Override - public OperationResult AddOperation(Operation operation) { - if (operation == null) { - return new OperationResult.OperationError("Operation can not be null"); - } - operations.add(operation); - return new OperationResult.Success(); - } - - /** - * Возвращает историю операций для указанного идентификатора банковского счета. - * - * @param bankAccountId идентификатор банковского счета, для которого требуется история операций. - * @return список операций {@link ArrayList} связанных с банковским счетом. - */ - @Override - public ArrayList GetOperationHistory(Integer bankAccountId) { - return operations; - } -} diff --git a/DataAccess/src/main/java/DataAccess/UserRepository.java b/DataAccess/src/main/java/DataAccess/UserRepository.java deleted file mode 100644 index 8cd18c2..0000000 --- a/DataAccess/src/main/java/DataAccess/UserRepository.java +++ /dev/null @@ -1,94 +0,0 @@ -package DataAccess; - -import lombok.NoArgsConstructor; -import Application.Abstractions.Repositories.IUserRepository; -import Application.Contracts.ResultTypes.UserResult; -import Application.Models.Entites.User; - -import java.util.ArrayList; -import java.util.Objects; - -/** - * Реализация репозитория для управления пользователями. - * Хранит пользователей в памяти (в списке) и реализует операции CRUD для сущности {@link User}. - * - *

Этот класс использует {@link ArrayList} для хранения данных и позволяет добавлять, обновлять, искать и удалять пользователей.

- */ -@NoArgsConstructor -public class UserRepository implements IUserRepository { - - private final ArrayList _users = new ArrayList<>(); - - /** - * Добавляет нового пользователя в хранилище. - * - * @param user объект пользователя, который будет добавлен. - * @return результат операции добавления, может быть ошибка создания пользователя, если пользователь равен {@code null}. - */ - @Override - public UserResult AddUser(User user) { - if (user == null) { - return new UserResult.UserCreationError("User can not be null"); - } - _users.add(user); - return new UserResult.Success(); - } - - /** - * Находит пользователя по его идентификатору. - * - * @param id идентификатор пользователя, которого нужно найти. - * @return найденный пользователь или {@code null}, если пользователь с таким идентификатором не существует. - */ - @Override - public User FindUserById(Integer id) { - if (id < 0) { - return null; - } - for (User user : _users) { - if (Objects.equals(user.getId(), id)) { - return user; - } - } - return null; - } - - /** - * Обновляет данные пользователя по его идентификатору. - * - * @param id идентификатор пользователя, которого нужно обновить. - * @param userUpdate объект с новыми данными пользователя. - * @return результат операции обновления, может быть ошибка, если параметры обновления неверны. - */ - @Override - public UserResult UpdateUser(Integer id, User userUpdate) { - if (userUpdate == null || id < 0) { - return new UserResult.UserUpdateError("Invalid update parameters"); - } - - for (int i = 0; i < _users.size(); ++i) { - User existingUser = _users.get(i); - if (Objects.equals(existingUser.getId(), id)) { - _users.set(i, userUpdate); - return new UserResult.Success(); - } - } - - return new UserResult.UserUpdateError("User update failed "); - } - - /** - * Удаляет пользователя по его идентификатору. - * - * @param id идентификатор пользователя, которого нужно удалить. - * @return результат операции удаления, может быть ошибка, если параметры удаления неверны. - */ - @Override - public UserResult DeleteUser(Integer id) { - if (id < 0) { - return new UserResult.UserDeletionError("Invalid delete parameters"); - } - _users.removeIf(user -> Objects.equals(user.getId(), id)); - return new UserResult.Success(); - } -} diff --git a/Presentation/src/main/java/Presentation/Console/Menu.java b/Presentation/src/main/java/Presentation/Console/Menu.java index ed7ce7f..ecda47b 100644 --- a/Presentation/src/main/java/Presentation/Console/Menu.java +++ b/Presentation/src/main/java/Presentation/Console/Menu.java @@ -1,19 +1,26 @@ package Presentation.Console; -import Application.Contracts.ResultTypes.BankAccountResult; -import Application.Contracts.ResultTypes.OperationResult; -import Application.Contracts.ResultTypes.UserResult; +import Application.Models.Entities.Operation; +import Application.ResultTypes.BankAccountResult; +import Application.ResultTypes.OperationResult; +import Application.ResultTypes.UserResult; import Application.Managers.UserManager; -import Application.Models.Entites.BankAccount; -import Application.Models.Entites.User; +import Application.Models.Entities.BankAccount; +import Application.Models.Entities.User; import Application.Models.Enums.HairColor; import Application.Models.Enums.Sex; -import Application.Models.Utils.IdGenerator; -import Application.Services.UserService; +import DAO.HibernateBankAccountDAO; +import DAO.HibernateOperationDAO; +import DAO.HibernateUserDAO; +import Presentation.Controllers.UserController; +import Services.BankAccountService; +import Services.OperationService; +import Services.UserService; import Presentation.Interfaces.IMenu; -import DataAccess.BankAccountRepository; -import DataAccess.OperationRepository; -import DataAccess.UserRepository; +import Utils.HibernateSessionFactoryUtil; +import org.hibernate.Hibernate; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; import java.util.Scanner; @@ -46,13 +53,13 @@ */ public class Menu implements IMenu { - private final IdGenerator userIdGenerator = new IdGenerator(); - private final IdGenerator bankAccountIdGenerator = new IdGenerator(); - private final UserService userService = new UserService( - new UserRepository(), - new BankAccountRepository(), - new OperationRepository(), - new UserManager()); + private final SessionFactory sf = HibernateSessionFactoryUtil.GetSessionFactory(); + private final UserController controller = new UserController( + new UserManager(), new UserService(new HibernateUserDAO(sf)), + new BankAccountService(new HibernateBankAccountDAO(sf)), + new OperationService(new HibernateOperationDAO(sf)) + ); + private final Scanner scanner = new Scanner(System.in); @@ -101,28 +108,49 @@ public void Run() { */ private void createUser() { System.out.print("Введите логин: "); - String login = scanner.nextLine(); + String login = scanner.nextLine().trim(); + if (login.isEmpty()) { + System.out.println("Логин не может быть пустым!"); + return; + } + System.out.print("Введите имя: "); - String name = scanner.nextLine(); - System.out.print("Введите возраст: "); - int age = scanner.nextInt(); - scanner.nextLine(); + String name = scanner.nextLine().trim(); + if (name.isEmpty()) { + System.out.println("Имя не может быть пустым!"); + return; + } + System.out.print("Введите возраст: "); + int age; + try { + age = Integer.parseInt(scanner.nextLine().trim()); + if (age <= 0) { + System.out.println("Возраст должен быть положительным числом!"); + return; + } + } catch (NumberFormatException e) { + System.out.println("Неверный формат возраста. Введите число."); + return; + } System.out.println("Выберите пол:"); System.out.println("1. Мужской"); System.out.println("2. Женский"); System.out.println("3. Неопределённый"); System.out.print("Введите цифру (1-3): "); - int sexChoice = scanner.nextInt(); - scanner.nextLine(); - - Sex sex = switch (sexChoice) { - case 1 -> Sex.Male; - case 2 -> Sex.Female; - default -> Sex.Undefined; - }; - + Sex sex; + try { + int sexChoice = Integer.parseInt(scanner.nextLine().trim()); + sex = switch (sexChoice) { + case 1 -> Sex.Male; + case 2 -> Sex.Female; + default -> Sex.Undefined; + }; + } catch (NumberFormatException e) { + System.out.println("Неверный выбор пола. Введите число от 1 до 3."); + return; + } System.out.println("Выберите цвет волос:"); System.out.println("1. Блонд"); @@ -136,26 +164,36 @@ private void createUser() { System.out.println("9. Белый"); System.out.println("10. Лысый"); System.out.print("Введите цифру (1-10): "); - int hairChoice = scanner.nextInt(); - scanner.nextLine(); - - HairColor hairColor = switch (hairChoice) { - case 1 -> HairColor.Blond; - case 2 -> HairColor.Ash; - case 3 -> HairColor.Brown; - case 4 -> HairColor.Auburn; - case 5 -> HairColor.Black; - case 6 -> HairColor.Dyed; - case 7 -> HairColor.Colored; - case 8 -> HairColor.Grey; - case 9 -> HairColor.White; - default -> HairColor.Bold; - }; - - User user = new User(userIdGenerator, login, name, age, sex, hairColor); - UserResult result = userService.CreateUser(user); - - System.out.println(result instanceof UserResult.Success ? "Пользователь создан!" : "Ошибка создания пользователя."); + HairColor hairColor; + try { + int hairChoice = Integer.parseInt(scanner.nextLine().trim()); + hairColor = switch (hairChoice) { + case 1 -> HairColor.Blond; + case 2 -> HairColor.Ash; + case 3 -> HairColor.Brown; + case 4 -> HairColor.Auburn; + case 5 -> HairColor.Black; + case 6 -> HairColor.Dyed; + case 7 -> HairColor.Colored; + case 8 -> HairColor.Grey; + case 9 -> HairColor.White; + default -> HairColor.Bold; + }; + } catch (NumberFormatException e) { + System.out.println("Неверный выбор цвета волос. Введите число от 1 до 10."); + return; + } + + // Создаем пользователя без использования IdGenerator, так как ID генерируется базой данных + User user = new User(login, name, age, sex, hairColor); + + // Вызываем метод создания пользователя через контроллер + UserResult result = controller.CreateUser(user); + if (result instanceof UserResult.Success) { + System.out.println("Пользователь создан!"); + } else { + System.out.println("Ошибка создания пользователя."); + } } /** @@ -164,12 +202,7 @@ private void createUser() { private void getUserInfo() { System.out.print("Введите ID пользователя: "); int userId = scanner.nextInt(); - User user = userService.get_userRepository().FindUserById(userId); - if (user != null) { - userService.GetUserInfo(user); - } else { - System.out.println("Пользователь не найден."); - } + controller.GetUserInfo(userId); } /** @@ -180,19 +213,15 @@ private void manageFriends() { int userId = scanner.nextInt(); System.out.print("Введите ID друга: "); int friendId = scanner.nextInt(); - - User user = userService.get_userRepository().FindUserById(userId); - User friend = userService.get_userRepository().FindUserById(friendId); - - if (user != null && friend != null) { + if (userId > 0 && friendId > 0) { System.out.print("Добавить друга (1) или удалить (2): "); int action = scanner.nextInt(); if (action == 1) { - userService.AddFriend(user, friend); + controller.AddFriend(userId, friendId); System.out.println("Друг добавлен."); } else if (action == 2) { - userService.RemoveFriend(user, friend); + controller.RemoveFriend(userId, friendId); System.out.println("Друг удален."); } else { System.out.println("Неверная команда."); @@ -208,18 +237,14 @@ private void manageFriends() { private void createBankAccount() { System.out.print("Введите ID пользователя: "); int userId = scanner.nextInt(); - - User user = userService.get_userRepository().FindUserById(userId); + User user = controller.GetUserById(userId); if (user == null) { - System.out.println("Пользователь не найден."); + System.out.println("Пользователь с ID " + userId + " не найден."); return; } - System.out.println("Найден пользователь: " + user.getName() + " (ID: " + user.getId() + ")"); - - BankAccount account = new BankAccount(bankAccountIdGenerator, user); - BankAccountResult result = userService.addBankAccount(user, account); - + BankAccount account = new BankAccount(user); + BankAccountResult result = controller.addBankAccount(userId, account); if (result instanceof BankAccountResult.Success) { System.out.println("Счет создан!"); } else { @@ -233,18 +258,14 @@ private void createBankAccount() { private void checkBalance() { System.out.print("Введите ID счета: "); int accountId = scanner.nextInt(); - BankAccount account = userService.get_bankAccountRepository().FindBankAccountById(accountId); + BankAccount account = controller.GetBankAccountById(accountId); - if (account != null) { - User user = userService.get_userRepository().FindUserById(account.getUserId()); - if (user != null) { - userService.CheckBalance(user, account); - } else { - System.out.println("Пользователь не найден."); - } - } else { + if (account == null) { System.out.println("Счет не найден."); + return; } + + controller.CheckBalance(account.getUser().getId(), accountId); } /** @@ -256,9 +277,9 @@ private void withdraw() { System.out.print("Введите сумму снятия: "); double amount = scanner.nextDouble(); - BankAccount account = userService.get_bankAccountRepository().FindBankAccountById(accountId); + BankAccount account = controller.GetBankAccountById(accountId); if (account != null) { - OperationResult result = userService.Withdraw(account, amount); + OperationResult result = controller.Withdraw(account, amount); if (result instanceof OperationResult.Success) { System.out.println("Деньги сняты."); @@ -279,9 +300,9 @@ private void deposit() { System.out.print("Введите сумму пополнения: "); double amount = scanner.nextDouble(); - BankAccount account = userService.get_bankAccountRepository().FindBankAccountById(accountId); + BankAccount account = controller.GetBankAccountById(accountId); if (account != null) { - OperationResult result = userService.Deposit(account, amount); + OperationResult result = controller.Deposit(account, amount); if (result instanceof OperationResult.Success) { System.out.println("Счет пополнен."); } else if (result instanceof OperationResult.OperationError error) { @@ -306,11 +327,11 @@ private void transfer() { System.out.print("Введите сумму перевода: "); double amount = Double.parseDouble(scanner.nextLine().trim().replace(',', '.')); - BankAccount fromAccount = userService.get_bankAccountRepository().FindBankAccountById(fromId); - BankAccount toAccount = userService.get_bankAccountRepository().FindBankAccountById(toId); + BankAccount fromAccount = controller.GetBankAccountById(fromId); + BankAccount toAccount = controller.GetBankAccountById(toId); if (fromAccount != null && toAccount != null) { - OperationResult result = userService.Transfer(fromAccount, toAccount, amount); + OperationResult result = controller.Transfer(fromAccount, toAccount, amount); if (result instanceof OperationResult.Success) { System.out.println("Перевод выполнен."); } else if (result instanceof OperationResult.OperationError error) { diff --git a/Application/src/main/java/Application/Contracts/Interfaces/IUserService.java b/Presentation/src/main/java/Presentation/Interfaces/IUserController.java similarity index 59% rename from Application/src/main/java/Application/Contracts/Interfaces/IUserService.java rename to Presentation/src/main/java/Presentation/Interfaces/IUserController.java index dac25eb..a59ac15 100644 --- a/Application/src/main/java/Application/Contracts/Interfaces/IUserService.java +++ b/Presentation/src/main/java/Presentation/Interfaces/IUserController.java @@ -1,17 +1,17 @@ -package Application.Contracts.Interfaces; +package Presentation.Interfaces; -import Application.Contracts.ResultTypes.BankAccountResult; -import Application.Contracts.ResultTypes.OperationResult; -import Application.Contracts.ResultTypes.UserResult; -import Application.Models.Entites.BankAccount; -import Application.Models.Entites.User; +import Application.ResultTypes.BankAccountResult; +import Application.ResultTypes.OperationResult; +import Application.ResultTypes.UserResult; +import Application.Models.Entities.BankAccount; +import Application.Models.Entities.User; /** * Интерфейс, предоставляющий операции для управления пользователями и их банковскими счетами. * Включает методы для создания, удаления пользователей, управления их друзьями и банковскими счетами, * а также выполнения различных операций с банковскими счетами. */ -public interface IUserService { +public interface IUserController { /** * Создание нового пользователя. @@ -21,6 +21,22 @@ public interface IUserService { */ UserResult CreateUser(User user); + /** + * Создание нового пользователя. + * + * @param id идентификатор пользователя, который должен быть найден. + * @return результат операции поиска пользователя. + */ + User GetUserById(int id); + + /** + * Создание нового пользователя. + * + * @param id идентификатор аккаунта, который должен быть найден. + * @return результат операции поиска аккаунта. + */ + BankAccount GetBankAccountById(int id); + /** * Удаление пользователя. * @@ -32,52 +48,52 @@ public interface IUserService { /** * Получение информации о пользователе. * - * @param user объект пользователя, информацию о котором необходимо получить. + * @param id идентификатор пользователя, информацию о котором необходимо получить. */ - void GetUserInfo(User user); + void GetUserInfo(int id); /** * Добавление пользователя в друзья. * - * @param user объект текущего пользователя. - * @param other объект пользователя, которого нужно добавить в друзья. + * @param userId идентификатор текущего пользователя. + * @param otherId идентификатор пользователя, которого нужно добавить в друзья. */ - void AddFriend(User user, User other); + void AddFriend(int userId, int otherId); /** * Удаление пользователя из списка друзей. * - * @param user объект текущего пользователя. - * @param other объект пользователя, которого нужно удалить из друзей. + * @param userId идентификатор текущего пользователя. + * @param otherId идентификатор пользователя, которого нужно удалить из друзей. */ - void RemoveFriend(User user, User other); + void RemoveFriend(int userId, int otherId); /** * Добавление нового банковского счета пользователю. * - * @param user объект пользователя, которому нужно добавить банковский счет. + * @param userId идентификатор пользователя, которому нужно добавить банковский счет. * @param bankAccount объект банковского счета, который нужно добавить. * @return результат операции добавления банковского счета. */ - BankAccountResult addBankAccount(User user, BankAccount bankAccount); + BankAccountResult addBankAccount(int userId, BankAccount bankAccount); /** * Удаление банковского счета пользователя. * - * @param user объект пользователя, чей банковский счет должен быть удален. + * @param userId идентификатор пользователя, чей банковский счет должен быть удален. * @param bankAccount объект банковского счета, который нужно удалить. * @return результат операции удаления банковского счета. */ - BankAccountResult RemoveBankAccount(User user, BankAccount bankAccount); + BankAccountResult RemoveBankAccount(int userId, BankAccount bankAccount); /** * Проверка баланса банковского счета пользователя. * - * @param user объект пользователя, чей баланс нужно проверить. - * @param bankAccount объект банковского счета, баланс которого нужно проверить. + * @param userId идентификатор пользователя, чей баланс нужно проверить. + * @param bankAccountId объект банковского счета, баланс которого нужно проверить. * @return результат операции проверки баланса. */ - OperationResult CheckBalance(User user, BankAccount bankAccount); + OperationResult CheckBalance(int userId, int bankAccountId); /** * Пополнение банковского счета. @@ -110,8 +126,8 @@ public interface IUserService { /** * Получение истории операций для конкретного банковского счета. * - * @param bankAccount объект банковского счета, для которого нужно получить историю операций. + * @param bankAccountId идентификатор банковского счета, для которого нужно получить историю операций. * @return результат операции получения истории. */ - OperationResult GetOperationHistory(BankAccount bankAccount); + OperationResult GetOperationHistory(int bankAccountId); } diff --git a/Presentation/src/test/java/BankTests.java b/Presentation/src/test/java/BankTests.java index 586778f..a5b7ec8 100644 --- a/Presentation/src/test/java/BankTests.java +++ b/Presentation/src/test/java/BankTests.java @@ -1,12 +1,13 @@ -import Application.Abstractions.Repositories.IBankAccountRepository; -import Application.Abstractions.Repositories.IOperationRepository; -import Application.Contracts.ResultTypes.OperationResult; -import Application.Models.Entites.BankAccount; -import Application.Models.Entites.User; +import Application.Managers.UserManager; +import Application.ResultTypes.OperationResult; +import Application.Models.Entities.BankAccount; +import Application.Models.Entities.User; import Application.Models.Enums.HairColor; import Application.Models.Enums.Sex; -import Application.Models.Utils.IdGenerator; -import Application.Services.UserService; +import Presentation.Controllers.UserController; +import Services.BankAccountService; +import Services.OperationService; +import Services.UserService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -20,83 +21,68 @@ public class BankTests { @Mock - private IBankAccountRepository bankAccountRepository; + private UserManager userManager; @Mock - private IOperationRepository operationRepository; + private UserService userService; + + @Mock + private BankAccountService bankAccountService; + + @Mock + private OperationService operationService; @InjectMocks - private UserService userService; + private UserController userController; private BankAccount bankAccount; + private User user; @BeforeEach void setUp() { MockitoAnnotations.initMocks(this); - User user = new User(new IdGenerator(), "lim0sha", "Sasha", 22, Sex.Male, HairColor.Brown); - bankAccount = new BankAccount(new IdGenerator(), user); + user = new User("lim0sha", "Sasha", 22, Sex.Male, HairColor.Brown); + bankAccount = new BankAccount(user); + bankAccount.setId(1); bankAccount.setBalance(100.0); } @Test void testWithdrawWithSufficientBalance() { Double withdrawAmount = 50.0; - Double initialBalance = bankAccount.getBalance(); + when(bankAccountService.Withdraw(bankAccount.getId(), withdrawAmount)).thenReturn(true); + doNothing().when(operationService).SaveOperation(any()); - when(bankAccountRepository.FindBankAccountById(bankAccount.getId())).thenReturn(bankAccount); - when(bankAccountRepository.UpdateBankAccountBalance(bankAccount.getId(), initialBalance - withdrawAmount)) - .thenAnswer(invocation -> { - bankAccount.setBalance(initialBalance - withdrawAmount); - return null; - }); - when(operationRepository.AddOperation(any())).thenReturn(new OperationResult.Success()); - - OperationResult operationResult = userService.Withdraw(bankAccount, withdrawAmount); + OperationResult operationResult = userController.Withdraw(bankAccount, withdrawAmount); assertInstanceOf(OperationResult.Success.class, operationResult); - assertEquals(initialBalance - withdrawAmount, bankAccount.getBalance(), 0.001); - verify(bankAccountRepository, times(1)).UpdateBankAccountBalance(bankAccount.getId(), initialBalance - withdrawAmount); - verify(operationRepository, times(1)).AddOperation(any()); - - assertEquals(50.0, bankAccount.getBalance(), 0.001); + verify(bankAccountService, times(1)).Withdraw(bankAccount.getId(), withdrawAmount); + verify(operationService, times(1)).SaveOperation(any()); } @Test void testWithdrawWithInsufficientBalance() { Double withdrawAmount = 150.0; + when(bankAccountService.Withdraw(bankAccount.getId(), withdrawAmount)).thenReturn(false); - when(bankAccountRepository.FindBankAccountById(bankAccount.getId())).thenReturn(bankAccount); - - OperationResult operationResult = userService.Withdraw(bankAccount, withdrawAmount); + OperationResult operationResult = userController.Withdraw(bankAccount, withdrawAmount); assertInstanceOf(OperationResult.OperationError.class, operationResult); - assertEquals("Not enough balance", ((OperationResult.OperationError) operationResult).getMessage()); - verify(bankAccountRepository, times(0)).UpdateBankAccountBalance(any(), anyDouble()); - verify(operationRepository, times(0)).AddOperation(any()); - - assertEquals(100.0, bankAccount.getBalance(), 0.001); + assertEquals("Not enough balance.", ((OperationResult.OperationError) operationResult).getMessage()); + verify(bankAccountService, times(1)).Withdraw(bankAccount.getId(), withdrawAmount); + verify(operationService, times(0)).SaveOperation(any()); // SaveOperation не должен вызываться } @Test void testDeposit() { Double depositAmount = 100.0; - Double initialBalance = bankAccount.getBalance(); - - when(bankAccountRepository.FindBankAccountById(bankAccount.getId())).thenReturn(bankAccount); - when(bankAccountRepository.UpdateBankAccountBalance(bankAccount.getId(), initialBalance + depositAmount)) - .thenAnswer(invocation -> { - bankAccount.setBalance(initialBalance + depositAmount); - return null; - }); - when(operationRepository.AddOperation(any())).thenReturn(new OperationResult.Success()); + when(bankAccountService.Deposit(bankAccount.getId(), depositAmount)).thenReturn(true); + doNothing().when(operationService).SaveOperation(any()); - OperationResult operationResult = userService.Deposit(bankAccount, depositAmount); + OperationResult operationResult = userController.Deposit(bankAccount, depositAmount); assertInstanceOf(OperationResult.Success.class, operationResult); - assertEquals(initialBalance + depositAmount, bankAccount.getBalance(), 0.001); - verify(bankAccountRepository, times(1)).UpdateBankAccountBalance(bankAccount.getId(), initialBalance + depositAmount); - verify(operationRepository, times(1)).AddOperation(any()); - - assertEquals(200.0, bankAccount.getBalance(), 0.001); + verify(bankAccountService, times(1)).Deposit(bankAccount.getId(), depositAmount); + verify(operationService, times(1)).SaveOperation(any()); } } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0223449..b718579 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,39 @@ 1.0-SNAPSHOT pom + + + org.hibernate + hibernate-core + 6.4.4.Final + + + + org.hibernate + hibernate-ehcache + 4.3.0.Beta3 + + + + org.postgresql + postgresql + 42.7.2 + + + + net.bytebuddy + byte-buddy + 1.14.7 + + + + org.flywaydb + flyway-core + 9.22.0 + + + + Application DataAccess @@ -28,6 +61,21 @@ + + + org.flywaydb + flyway-maven-plugin + 9.22.0 + + jdbc:postgresql://localhost:5432/JavaLabsDb + postgres + limosha + + classpath:db/migration + + true + + \ No newline at end of file From 950c15e9b78a52c96683bad8231c91dae18f531b Mon Sep 17 00:00:00 2001 From: Alexander Kim Date: Wed, 2 Apr 2025 16:56:47 +0300 Subject: [PATCH 2/4] fix: build failed [git add required] --- .../main/resources/db/migration/V3__init.sql | 56 +++++ .../java/DAO/HibernateBankAccountDAO.java | 109 ++++++++++ .../main/java/DAO/HibernateOperationDAO.java | 71 +++++++ .../src/main/java/DAO/HibernateUserDAO.java | 71 +++++++ .../java/DAO/Interfaces/IBankAccountDAO.java | 12 ++ .../java/DAO/Interfaces/IOperationDAO.java | 13 ++ .../main/java/DAO/Interfaces/IUserDAO.java | 12 ++ .../java/Services/BankAccountService.java | 42 ++++ .../Interfaces/IBankAccountService.java | 12 ++ .../Interfaces/IOperationService.java | 12 ++ .../Services/Interfaces/IUserService.java | 9 + .../main/java/Services/OperationService.java | 35 ++++ .../src/main/java/Services/UserService.java | 28 +++ .../Utils/HibernateSessionFactoryUtil.java | 35 ++++ DataAccess/src/main/resources/application.yml | 9 + .../main/resources/db/migration/V1__init.sql | 32 +++ .../db/migration/V2__drop_tables.sql | 4 + .../src/main/resources/hibernate.cfg.xml | 27 +++ .../Controllers/UserController.java | 191 ++++++++++++++++++ 19 files changed, 780 insertions(+) create mode 100644 Application/src/main/resources/db/migration/V3__init.sql create mode 100644 DataAccess/src/main/java/DAO/HibernateBankAccountDAO.java create mode 100644 DataAccess/src/main/java/DAO/HibernateOperationDAO.java create mode 100644 DataAccess/src/main/java/DAO/HibernateUserDAO.java create mode 100644 DataAccess/src/main/java/DAO/Interfaces/IBankAccountDAO.java create mode 100644 DataAccess/src/main/java/DAO/Interfaces/IOperationDAO.java create mode 100644 DataAccess/src/main/java/DAO/Interfaces/IUserDAO.java create mode 100644 DataAccess/src/main/java/Services/BankAccountService.java create mode 100644 DataAccess/src/main/java/Services/Interfaces/IBankAccountService.java create mode 100644 DataAccess/src/main/java/Services/Interfaces/IOperationService.java create mode 100644 DataAccess/src/main/java/Services/Interfaces/IUserService.java create mode 100644 DataAccess/src/main/java/Services/OperationService.java create mode 100644 DataAccess/src/main/java/Services/UserService.java create mode 100644 DataAccess/src/main/java/Utils/HibernateSessionFactoryUtil.java create mode 100644 DataAccess/src/main/resources/application.yml create mode 100644 DataAccess/src/main/resources/db/migration/V1__init.sql create mode 100644 DataAccess/src/main/resources/db/migration/V2__drop_tables.sql create mode 100644 DataAccess/src/main/resources/hibernate.cfg.xml create mode 100644 Presentation/src/main/java/Presentation/Controllers/UserController.java diff --git a/Application/src/main/resources/db/migration/V3__init.sql b/Application/src/main/resources/db/migration/V3__init.sql new file mode 100644 index 0000000..01d855f --- /dev/null +++ b/Application/src/main/resources/db/migration/V3__init.sql @@ -0,0 +1,56 @@ +CREATE SEQUENCE IF NOT EXISTS bankaccounts_id_seq START WITH 1 INCREMENT BY 1; + +CREATE SEQUENCE IF NOT EXISTS operations_id_seq START WITH 1 INCREMENT BY 1; + +CREATE SEQUENCE IF NOT EXISTS users_id_seq START WITH 1 INCREMENT BY 1; + +CREATE TABLE bankaccounts +( + id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, + balance DOUBLE PRECISION NOT NULL, + userlogin VARCHAR(255) NOT NULL, + userid INTEGER NOT NULL, + CONSTRAINT bankaccounts_pkey PRIMARY KEY (id) +); + +CREATE TABLE friends +( + userid INTEGER NOT NULL, + friendid INTEGER NOT NULL, + CONSTRAINT friends_pkey PRIMARY KEY (userid, friendid) +); + +CREATE TABLE operations +( + id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, + accountid INTEGER NOT NULL, + type VARCHAR(255) NOT NULL, + amount DOUBLE PRECISION NOT NULL, + CONSTRAINT operations_pkey PRIMARY KEY (id) +); + +CREATE TABLE users +( + id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, + login VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + age INTEGER NOT NULL, + sex VARCHAR(255) NOT NULL, + haircolor VARCHAR(255), + CONSTRAINT users_pkey PRIMARY KEY (id) +); + +ALTER TABLE users + ADD CONSTRAINT users_login_key UNIQUE (login); + +ALTER TABLE bankaccounts + ADD CONSTRAINT bankaccounts_userid_fkey FOREIGN KEY (userid) REFERENCES users (id) ON DELETE NO ACTION; + +ALTER TABLE friends + ADD CONSTRAINT friends_friendid_fkey FOREIGN KEY (friendid) REFERENCES users (id) ON DELETE NO ACTION; + +ALTER TABLE friends + ADD CONSTRAINT friends_userid_fkey FOREIGN KEY (userid) REFERENCES users (id) ON DELETE NO ACTION; + +ALTER TABLE operations + ADD CONSTRAINT operations_accountid_fkey FOREIGN KEY (accountid) REFERENCES bankaccounts (id) ON DELETE NO ACTION; \ No newline at end of file diff --git a/DataAccess/src/main/java/DAO/HibernateBankAccountDAO.java b/DataAccess/src/main/java/DAO/HibernateBankAccountDAO.java new file mode 100644 index 0000000..bd03d61 --- /dev/null +++ b/DataAccess/src/main/java/DAO/HibernateBankAccountDAO.java @@ -0,0 +1,109 @@ +package DAO; + +import Application.Models.Entities.BankAccount; +import DAO.Interfaces.IBankAccountDAO; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +public class HibernateBankAccountDAO implements IBankAccountDAO { + private final SessionFactory sessionFactory; + + public HibernateBankAccountDAO(SessionFactory sf) { + this.sessionFactory = sf; + } + + public BankAccount GetBankAccountByID(int id) { + try (Session session = sessionFactory.openSession()) { + return session.get(BankAccount.class, id); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public void SaveBankAccount(BankAccount account) { + try (Session session = sessionFactory.openSession()) { + Transaction tx = null; + try { + tx = session.beginTransaction(); + session.saveOrUpdate(account); + tx.commit(); + } catch (Exception e) { + if (tx != null) { + tx.rollback(); + } + e.printStackTrace(); + } + } + } + + public void DeleteBankAccount(BankAccount bankAccount) { + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + session.delete(bankAccount); + tx.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public boolean Deposit(int accountId, double amount) { + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + BankAccount account = session.get(BankAccount.class, accountId); + if (account != null) { + account.setBalance(account.getBalance() + amount); + session.saveOrUpdate(account); + tx.commit(); + return true; + } + tx.rollback(); + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + public boolean Withdraw(int accountId, double amount) { + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + BankAccount account = session.get(BankAccount.class, accountId); + if (account != null && account.getBalance() >= amount) { + account.setBalance(account.getBalance() - amount); + session.saveOrUpdate(account); + tx.commit(); + return true; + } + tx.rollback(); + return false; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean Transfer(int accountFromId, int accountToId, double amount) { + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + + BankAccount accountFrom = session.get(BankAccount.class, accountFromId); + BankAccount accountTo = session.get(BankAccount.class, accountToId); + + if (accountFrom != null && accountTo != null && accountFrom.getBalance() >= amount) { + accountFrom.setBalance(accountFrom.getBalance() - amount); + accountTo.setBalance(accountTo.getBalance() + amount); + session.saveOrUpdate(accountFrom); + session.saveOrUpdate(accountTo); + tx.commit(); + return true; + } + + tx.rollback(); + return false; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/DataAccess/src/main/java/DAO/HibernateOperationDAO.java b/DataAccess/src/main/java/DAO/HibernateOperationDAO.java new file mode 100644 index 0000000..152f10f --- /dev/null +++ b/DataAccess/src/main/java/DAO/HibernateOperationDAO.java @@ -0,0 +1,71 @@ +package DAO; + +import Application.Models.Entities.Operation; +import DAO.Interfaces.IOperationDAO; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import java.util.ArrayList; +import java.util.List; + +public class HibernateOperationDAO implements IOperationDAO { + private final SessionFactory sessionFactory; + + public HibernateOperationDAO(SessionFactory sf) { + sessionFactory = sf; + } + @Override + public Operation GetOperationById(int id) { + try (Session session = sessionFactory.openSession()) { + return session.get(Operation.class, id); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public void SaveOperation(Operation operation) { + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + session.saveOrUpdate(operation); + tx.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void DeleteOperation(Operation operation) { + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + session.delete(operation); + tx.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public List FindAllOperations() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("FROM Operation", Operation.class).list(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public List FindAllOperationsByAccountId(int id) { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("FROM Operation WHERE bankAccount.id = :accountId", Operation.class) + .setParameter("accountId", id) + .getResultList(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/DataAccess/src/main/java/DAO/HibernateUserDAO.java b/DataAccess/src/main/java/DAO/HibernateUserDAO.java new file mode 100644 index 0000000..d598cdc --- /dev/null +++ b/DataAccess/src/main/java/DAO/HibernateUserDAO.java @@ -0,0 +1,71 @@ +package DAO; + +import Application.Models.Entities.User; +import DAO.Interfaces.IUserDAO; +import org.hibernate.Hibernate; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import java.util.List; + +public class HibernateUserDAO implements IUserDAO { + private final SessionFactory sessionFactory; + + public HibernateUserDAO(SessionFactory sf) { + sessionFactory = sf; + } + + @Override + public void SaveUser(User user) { + if (user == null) { + throw new IllegalArgumentException("Пользователь не может быть null"); + } + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + session.saveOrUpdate(user); + tx.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void DeleteUser(User user) { + if (user == null || user.getId() == null) { + throw new IllegalArgumentException("Пользователь или его ID не могут быть null"); + } + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + session.delete(user); + tx.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public User FindUserById(int id) { + try (Session session = sessionFactory.openSession()) { + User user = session.get(User.class, id); + if (user != null) { + Hibernate.initialize(user.getBankAccounts()); + Hibernate.initialize(user.getFriends()); + } + return user; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public List FindAllUsers() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("FROM User", User.class).list(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/DataAccess/src/main/java/DAO/Interfaces/IBankAccountDAO.java b/DataAccess/src/main/java/DAO/Interfaces/IBankAccountDAO.java new file mode 100644 index 0000000..b535210 --- /dev/null +++ b/DataAccess/src/main/java/DAO/Interfaces/IBankAccountDAO.java @@ -0,0 +1,12 @@ +package DAO.Interfaces; + +import Application.Models.Entities.BankAccount; + +public interface IBankAccountDAO { + BankAccount GetBankAccountByID(int id); + void SaveBankAccount(BankAccount bankAccount); + void DeleteBankAccount(BankAccount bankAccount); + boolean Deposit(int accountId, double amount); + boolean Withdraw(int accountId, double amount); + boolean Transfer(int accountFromId, int accountToId, double amount); +} diff --git a/DataAccess/src/main/java/DAO/Interfaces/IOperationDAO.java b/DataAccess/src/main/java/DAO/Interfaces/IOperationDAO.java new file mode 100644 index 0000000..deb824a --- /dev/null +++ b/DataAccess/src/main/java/DAO/Interfaces/IOperationDAO.java @@ -0,0 +1,13 @@ +package DAO.Interfaces; + +import Application.Models.Entities.Operation; + +import java.util.List; + +public interface IOperationDAO { + Operation GetOperationById(int id); + void SaveOperation(Operation operation); + void DeleteOperation(Operation operation); + List FindAllOperations(); + List FindAllOperationsByAccountId(int id); +} diff --git a/DataAccess/src/main/java/DAO/Interfaces/IUserDAO.java b/DataAccess/src/main/java/DAO/Interfaces/IUserDAO.java new file mode 100644 index 0000000..8e055fc --- /dev/null +++ b/DataAccess/src/main/java/DAO/Interfaces/IUserDAO.java @@ -0,0 +1,12 @@ +package DAO.Interfaces; + +import Application.Models.Entities.User; + +import java.util.List; + +public interface IUserDAO { + void SaveUser(User user); + void DeleteUser(User user); + User FindUserById(int id); + List FindAllUsers(); +} diff --git a/DataAccess/src/main/java/Services/BankAccountService.java b/DataAccess/src/main/java/Services/BankAccountService.java new file mode 100644 index 0000000..fe291f0 --- /dev/null +++ b/DataAccess/src/main/java/Services/BankAccountService.java @@ -0,0 +1,42 @@ +package Services; + +import Application.Models.Entities.BankAccount; +import DAO.HibernateBankAccountDAO; +import Services.Interfaces.IBankAccountService; + +public class BankAccountService implements IBankAccountService { + private final HibernateBankAccountDAO BankAccountDAO; + + public BankAccountService(HibernateBankAccountDAO bankAccountDAO) { + BankAccountDAO = bankAccountDAO; + } + @Override + public BankAccount GetAccount(int id) { + return BankAccountDAO.GetBankAccountByID(id); + } + + @Override + public void UpdateAccount(BankAccount account) { + BankAccountDAO.SaveBankAccount(account); + } + + @Override + public void DeleteAccount(BankAccount account) { + BankAccountDAO.DeleteBankAccount(account); + } + + @Override + public boolean Deposit(int accountId, double amount) { + return BankAccountDAO.Deposit(accountId, amount); + } + + @Override + public boolean Withdraw(int accountId, double amount) { + return BankAccountDAO.Withdraw(accountId, amount); + } + + @Override + public boolean Transfer(int accountFromId, int accountToId, double amount) { + return BankAccountDAO.Transfer(accountFromId, accountToId, amount); + } +} diff --git a/DataAccess/src/main/java/Services/Interfaces/IBankAccountService.java b/DataAccess/src/main/java/Services/Interfaces/IBankAccountService.java new file mode 100644 index 0000000..eac5e81 --- /dev/null +++ b/DataAccess/src/main/java/Services/Interfaces/IBankAccountService.java @@ -0,0 +1,12 @@ +package Services.Interfaces; + +import Application.Models.Entities.BankAccount; + +public interface IBankAccountService { + BankAccount GetAccount(int id); + void UpdateAccount(BankAccount account); + void DeleteAccount(BankAccount account); + boolean Deposit(int accountId, double amount); + boolean Withdraw(int accountId, double amount); + boolean Transfer(int accountFromId, int accountToId, double amount); +} diff --git a/DataAccess/src/main/java/Services/Interfaces/IOperationService.java b/DataAccess/src/main/java/Services/Interfaces/IOperationService.java new file mode 100644 index 0000000..f86fd3e --- /dev/null +++ b/DataAccess/src/main/java/Services/Interfaces/IOperationService.java @@ -0,0 +1,12 @@ +package Services.Interfaces; + +import Application.Models.Entities.Operation; + +import java.util.List; + +public interface IOperationService { + Operation GetOperation(int id); + void SaveOperation(Operation operation); + void DeleteOperation(Operation operation); + List FindAllOperationsByAccountId(int id); +} diff --git a/DataAccess/src/main/java/Services/Interfaces/IUserService.java b/DataAccess/src/main/java/Services/Interfaces/IUserService.java new file mode 100644 index 0000000..54e8164 --- /dev/null +++ b/DataAccess/src/main/java/Services/Interfaces/IUserService.java @@ -0,0 +1,9 @@ +package Services.Interfaces; + +import Application.Models.Entities.User; + +public interface IUserService { + User GetUser(int id); + void SaveUser(User user); + void DeleteUser(User user); +} diff --git a/DataAccess/src/main/java/Services/OperationService.java b/DataAccess/src/main/java/Services/OperationService.java new file mode 100644 index 0000000..f2920a1 --- /dev/null +++ b/DataAccess/src/main/java/Services/OperationService.java @@ -0,0 +1,35 @@ +package Services; + +import Application.Models.Entities.Operation; +import DAO.HibernateOperationDAO; +import Services.Interfaces.IOperationService; + +import java.util.List; + +public class OperationService implements IOperationService { + private final HibernateOperationDAO OperationDAO; + + public OperationService(HibernateOperationDAO operationDAO) { + OperationDAO = operationDAO; + } + + @Override + public Operation GetOperation(int id) { + return OperationDAO.GetOperationById(id); + } + + @Override + public void SaveOperation(Operation operation) { + OperationDAO.SaveOperation(operation); + } + + @Override + public void DeleteOperation(Operation operation) { + OperationDAO.DeleteOperation(operation); + } + + @Override + public List FindAllOperationsByAccountId(int id) { + return OperationDAO.FindAllOperationsByAccountId(id); + } +} diff --git a/DataAccess/src/main/java/Services/UserService.java b/DataAccess/src/main/java/Services/UserService.java new file mode 100644 index 0000000..2339ea4 --- /dev/null +++ b/DataAccess/src/main/java/Services/UserService.java @@ -0,0 +1,28 @@ +package Services; + +import Application.Models.Entities.User; +import DAO.HibernateUserDAO; +import Services.Interfaces.IUserService; + +public class UserService implements IUserService { + private final HibernateUserDAO UserDAO; + + public UserService(HibernateUserDAO userDAO) { + UserDAO = userDAO; + } + + @Override + public User GetUser(int id) { + return UserDAO.FindUserById(id); + } + + @Override + public void SaveUser(User user) { + UserDAO.SaveUser(user); + } + + @Override + public void DeleteUser(User user) { + UserDAO.DeleteUser(user); + } +} diff --git a/DataAccess/src/main/java/Utils/HibernateSessionFactoryUtil.java b/DataAccess/src/main/java/Utils/HibernateSessionFactoryUtil.java new file mode 100644 index 0000000..230c5e8 --- /dev/null +++ b/DataAccess/src/main/java/Utils/HibernateSessionFactoryUtil.java @@ -0,0 +1,35 @@ +package Utils; + +import Application.Models.Entities.BankAccount; +import Application.Models.Entities.Operation; +import Application.Models.Entities.User; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; + + +public class HibernateSessionFactoryUtil { + private static SessionFactory SessionFactory; + + private HibernateSessionFactoryUtil() {} + + public static SessionFactory GetSessionFactory() { + if (SessionFactory == null) { + try { + Configuration config = new Configuration().configure(); + + config.addAnnotatedClass(User.class); + config.addAnnotatedClass(BankAccount.class); + config.addAnnotatedClass(Operation.class); + StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() + .applySettings(config.getProperties()); + + SessionFactory = config.buildSessionFactory(builder.build()); + } catch (Exception e) { + System.out.println("Error in getSessionFactory: " + e.getMessage()); + throw new RuntimeException("Failed to create sessionFactory", e); + } + } + return SessionFactory; + } +} diff --git a/DataAccess/src/main/resources/application.yml b/DataAccess/src/main/resources/application.yml new file mode 100644 index 0000000..204317a --- /dev/null +++ b/DataAccess/src/main/resources/application.yml @@ -0,0 +1,9 @@ +spring: + datasource: + url: jdbc:postgresql://localhost:5432/JavaLabsDb + username: postgres + password: limosha + flyway: + enabled: true + locations: classpath:db/migration + baseline-on-migrate: true \ No newline at end of file diff --git a/DataAccess/src/main/resources/db/migration/V1__init.sql b/DataAccess/src/main/resources/db/migration/V1__init.sql new file mode 100644 index 0000000..26dd68f --- /dev/null +++ b/DataAccess/src/main/resources/db/migration/V1__init.sql @@ -0,0 +1,32 @@ +CREATE TABLE Users +( + id SERIAL PRIMARY KEY, + login VARCHAR(255) UNIQUE NOT NULL, + name VARCHAR(255) NOT NULL, + age INT NOT NULL, + sex VARCHAR(255) NOT NULL, + hairColor VARCHAR(255) +); + +CREATE TABLE BankAccounts +( + id SERIAL PRIMARY KEY, + balance DOUBLE PRECISION NOT NULL, + userLogin VARCHAR(255) NOT NULL, + userId INT NOT NULL REFERENCES Users (id) +); + +CREATE TABLE Operations +( + id SERIAL PRIMARY KEY, + accountId INT NOT NULL REFERENCES BankAccounts (id), + type VARCHAR(255) NOT NULL, + amount DOUBLE PRECISION NOT NULL +); + +CREATE TABLE Friends +( + userId INT NOT NULL REFERENCES Users (id), + friendId INT NOT NULL REFERENCES Users (id), + PRIMARY KEY (userId, friendId) +); \ No newline at end of file diff --git a/DataAccess/src/main/resources/db/migration/V2__drop_tables.sql b/DataAccess/src/main/resources/db/migration/V2__drop_tables.sql new file mode 100644 index 0000000..82e47f8 --- /dev/null +++ b/DataAccess/src/main/resources/db/migration/V2__drop_tables.sql @@ -0,0 +1,4 @@ +DROP TABLE Friends; +DROP TABLE Operations; +DROP TABLE BankAccounts; +DROP TABLE Users; \ No newline at end of file diff --git a/DataAccess/src/main/resources/hibernate.cfg.xml b/DataAccess/src/main/resources/hibernate.cfg.xml new file mode 100644 index 0000000..5e06fc0 --- /dev/null +++ b/DataAccess/src/main/resources/hibernate.cfg.xml @@ -0,0 +1,27 @@ + + + + + + org.postgresql.Driver + jdbc:postgresql://localhost:5432/JavaLabsDb + postgres + limosha + + + org.hibernate.dialect.PostgreSQLDialect + + + true + true + + validate + + + + + + + diff --git a/Presentation/src/main/java/Presentation/Controllers/UserController.java b/Presentation/src/main/java/Presentation/Controllers/UserController.java new file mode 100644 index 0000000..74bee86 --- /dev/null +++ b/Presentation/src/main/java/Presentation/Controllers/UserController.java @@ -0,0 +1,191 @@ +package Presentation.Controllers; + +import Application.Managers.UserManager; +import Application.Models.Entities.BankAccount; +import Application.Models.Entities.Operation; +import Application.Models.Entities.User; +import Application.Models.Enums.OperationType; +import Application.ResultTypes.BankAccountResult; +import Application.ResultTypes.OperationResult; +import Application.ResultTypes.UserResult; +import Presentation.Interfaces.IUserController; +import Services.BankAccountService; +import Services.OperationService; +import Services.UserService; + +import java.util.ArrayList; +import java.util.List; + +public class UserController implements IUserController { + private final UserManager UserManager; + private final UserService UserService; + private final BankAccountService BankAccountService; + private final OperationService OperationService; + + public UserController(UserManager userManager, UserService userService, BankAccountService bankAccountService, OperationService operationService) { + UserManager = userManager; + UserService = userService; + BankAccountService = bankAccountService; + OperationService = operationService; + } + + @Override + public UserResult CreateUser(User user) { + if (user == null || user.getLogin() == null || user.getName() == null) { + return new UserResult.UserCreationError("Некорректные данные пользователя"); + } + UserService.SaveUser(user); + return new UserResult.Success(); + } + + @Override + public User GetUserById(int id) { + try { + return UserService.GetUser(id); + } catch (Exception e) { + return null; + } + } + + @Override + public BankAccount GetBankAccountById(int id) { + try { + return BankAccountService.GetAccount(id); + } catch (Exception e) { + return null; + } + } + + @Override + public UserResult DeleteUser(User user) { + try { + UserService.DeleteUser(user); + return new UserResult.Success(); + } catch (Exception e) { + return new UserResult.UserDeletionError(e.getMessage()); + } + } + + @Override + public void GetUserInfo(int id) { + UserManager.GetUserInfo(UserService.GetUser(id)); + } + + @Override + public void AddFriend(int userId, int otherId) { + User user1 = UserService.GetUser(userId); + User user2 = UserService.GetUser(otherId); + UserManager.AddFriend(user1, user2); + UserService.SaveUser(user1); + UserService.SaveUser(user2); + } + + @Override + public void RemoveFriend(int userId, int otherId) { + User user1 = UserService.GetUser(userId); + User user2 = UserService.GetUser(otherId); + UserManager.RemoveFriend(user1, user2); + UserService.SaveUser(user1); + UserService.SaveUser(user2); + } + + @Override + public BankAccountResult addBankAccount(int userId, BankAccount bankAccount) { + try { + User user = UserService.GetUser(userId); + UserManager.AddBankAccount(user, bankAccount); + UserService.SaveUser(user); + BankAccountService.UpdateAccount(bankAccount); + return new BankAccountResult.Success(); + } catch (Exception e) { + return new BankAccountResult.BankAccountCreationError(e.getMessage()); + } + } + + @Override + public BankAccountResult RemoveBankAccount(int userId, BankAccount bankAccount) { + try { + User user = UserService.GetUser(userId); + UserManager.RemoveBankAccount(user, bankAccount); + UserService.SaveUser(user); + BankAccountService.UpdateAccount(bankAccount); + return new BankAccountResult.Success(); + } catch (Exception e) { + return new BankAccountResult.BankAccountDeletionError(e.getMessage()); + } + } + + @Override + public OperationResult CheckBalance(int userId, int accountId) { + BankAccount account = BankAccountService.GetAccount(accountId); + if (account == null || account.getUser().getId() != userId) { + return new OperationResult.OperationError("Счет не найден или принадлежит другому пользователю."); + } + System.out.println("Баланс счета: " + account.getBalance()); + return new OperationResult.Success(); + } + + @Override + public OperationResult Deposit(BankAccount bankAccount, Double amount) { + try { + BankAccountService.Deposit(bankAccount.getId(), amount); + OperationService.SaveOperation(new Operation(bankAccount, OperationType.Deposit, amount)); + return new OperationResult.Success(); + } catch (Exception e) { + return new OperationResult.OperationError(e.getMessage()); + } + } + + @Override + public OperationResult Withdraw(BankAccount bankAccount, Double amount) { + try { + boolean success = BankAccountService.Withdraw(bankAccount.getId(), amount); + if (!success) { + return new OperationResult.OperationError("Not enough balance."); + } + OperationService.SaveOperation(new Operation(bankAccount, OperationType.Withdraw, amount)); + return new OperationResult.Success(); + } catch (Exception e) { + return new OperationResult.OperationError(e.getMessage()); + } + } + + @Override + public OperationResult Transfer(BankAccount bankAccount1, BankAccount bankAccount2, Double amount) { + try { + User user1 = UserService.GetUser(bankAccount1.getUser().getId()); + User user2 = UserService.GetUser(bankAccount2.getUser().getId()); + + double commissionRate = user1.getId().equals(user2.getId()) ? 0.00 + : user1.getFriends().stream().anyMatch(f -> f.getId().equals(user2.getId())) ? 0.03 + : 0.10; + double commission = amount * commissionRate; + double totalAmount = amount + commission; + + boolean success = BankAccountService.Transfer(bankAccount1.getId(), bankAccount2.getId(), totalAmount); + if (!success) { + return new OperationResult.OperationError("Insufficient funds, including commission."); + } + + OperationService.SaveOperation(new Operation(bankAccount1, OperationType.Transfer, totalAmount)); + OperationService.SaveOperation(new Operation(bankAccount2, OperationType.Deposit, amount)); + + return new OperationResult.Success(); + } catch (Exception e) { + return new OperationResult.OperationError(e.getMessage()); + } + } + + @Override + public OperationResult GetOperationHistory(int bankAccountId) { + try { + BankAccount account = BankAccountService.GetAccount(bankAccountId); + List operations = OperationService.FindAllOperationsByAccountId(account.getId()); + return UserManager.PrintHistory(account, operations); + } catch (Exception e) { + e.printStackTrace(); + return new OperationResult.OperationError(e.getMessage()); + } + } + +} From 2cf4fcc0058ebfefd205f8d7176a408f4eff450f Mon Sep 17 00:00:00 2001 From: Alexander Kim Date: Wed, 2 Apr 2025 17:52:50 +0300 Subject: [PATCH 3/4] feat: add tx rollbacks; fix: primitive double in tests --- .../java/DAO/HibernateBankAccountDAO.java | 112 +++++++++--------- .../main/java/DAO/HibernateOperationDAO.java | 35 ++++-- .../src/main/java/DAO/HibernateUserDAO.java | 46 +++++-- Presentation/src/test/java/BankTests.java | 6 +- 4 files changed, 129 insertions(+), 70 deletions(-) diff --git a/DataAccess/src/main/java/DAO/HibernateBankAccountDAO.java b/DataAccess/src/main/java/DAO/HibernateBankAccountDAO.java index bd03d61..f2c2d21 100644 --- a/DataAccess/src/main/java/DAO/HibernateBankAccountDAO.java +++ b/DataAccess/src/main/java/DAO/HibernateBankAccountDAO.java @@ -40,70 +40,76 @@ public void SaveBankAccount(BankAccount account) { public void DeleteBankAccount(BankAccount bankAccount) { try (Session session = sessionFactory.openSession()) { - Transaction tx = session.beginTransaction(); - session.delete(bankAccount); - tx.commit(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public boolean Deposit(int accountId, double amount) { - try (Session session = sessionFactory.openSession()) { - Transaction tx = session.beginTransaction(); - BankAccount account = session.get(BankAccount.class, accountId); - if (account != null) { - account.setBalance(account.getBalance() + amount); - session.saveOrUpdate(account); + Transaction tx = null; + try { + tx = session.beginTransaction(); + session.delete(bankAccount); tx.commit(); - return true; + } catch (Exception e) { + if (tx != null) { + tx.rollback(); + } + e.printStackTrace(); } - tx.rollback(); - } catch (Exception e) { - e.printStackTrace(); } - return false; } - public boolean Withdraw(int accountId, double amount) { - try (Session session = sessionFactory.openSession()) { - Transaction tx = session.beginTransaction(); - BankAccount account = session.get(BankAccount.class, accountId); - if (account != null && account.getBalance() >= amount) { - account.setBalance(account.getBalance() - amount); - session.saveOrUpdate(account); - tx.commit(); - return true; + public boolean Deposit ( int accountId, double amount){ + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + BankAccount account = session.get(BankAccount.class, accountId); + if (account != null) { + account.setBalance(account.getBalance() + amount); + session.saveOrUpdate(account); + tx.commit(); + return true; + } + tx.rollback(); + } catch (Exception e) { + e.printStackTrace(); } - tx.rollback(); - return false; - } catch (Exception e) { - e.printStackTrace(); return false; } - } - public boolean Transfer(int accountFromId, int accountToId, double amount) { - try (Session session = sessionFactory.openSession()) { - Transaction tx = session.beginTransaction(); + public boolean Withdraw ( int accountId, double amount){ + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); + BankAccount account = session.get(BankAccount.class, accountId); + if (account != null && account.getBalance() >= amount) { + account.setBalance(account.getBalance() - amount); + session.saveOrUpdate(account); + tx.commit(); + return true; + } + tx.rollback(); + return false; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } - BankAccount accountFrom = session.get(BankAccount.class, accountFromId); - BankAccount accountTo = session.get(BankAccount.class, accountToId); + public boolean Transfer ( int accountFromId, int accountToId, double amount){ + try (Session session = sessionFactory.openSession()) { + Transaction tx = session.beginTransaction(); - if (accountFrom != null && accountTo != null && accountFrom.getBalance() >= amount) { - accountFrom.setBalance(accountFrom.getBalance() - amount); - accountTo.setBalance(accountTo.getBalance() + amount); - session.saveOrUpdate(accountFrom); - session.saveOrUpdate(accountTo); - tx.commit(); - return true; - } + BankAccount accountFrom = session.get(BankAccount.class, accountFromId); + BankAccount accountTo = session.get(BankAccount.class, accountToId); - tx.rollback(); - return false; - } catch (Exception e) { - e.printStackTrace(); - return false; + if (accountFrom != null && accountTo != null && accountFrom.getBalance() >= amount) { + accountFrom.setBalance(accountFrom.getBalance() - amount); + accountTo.setBalance(accountTo.getBalance() + amount); + session.saveOrUpdate(accountFrom); + session.saveOrUpdate(accountTo); + tx.commit(); + return true; + } + + tx.rollback(); + return false; + } catch (Exception e) { + e.printStackTrace(); + return false; + } } } -} diff --git a/DataAccess/src/main/java/DAO/HibernateOperationDAO.java b/DataAccess/src/main/java/DAO/HibernateOperationDAO.java index 152f10f..4cf7954 100644 --- a/DataAccess/src/main/java/DAO/HibernateOperationDAO.java +++ b/DataAccess/src/main/java/DAO/HibernateOperationDAO.java @@ -15,6 +15,7 @@ public class HibernateOperationDAO implements IOperationDAO { public HibernateOperationDAO(SessionFactory sf) { sessionFactory = sf; } + @Override public Operation GetOperationById(int id) { try (Session session = sessionFactory.openSession()) { @@ -27,23 +28,43 @@ public Operation GetOperationById(int id) { @Override public void SaveOperation(Operation operation) { - try (Session session = sessionFactory.openSession()) { - Transaction tx = session.beginTransaction(); + Session session = null; + Transaction tx = null; + try { + session = sessionFactory.openSession(); + tx = session.beginTransaction(); session.saveOrUpdate(operation); tx.commit(); } catch (Exception e) { + if (tx != null) { + tx.rollback(); + } e.printStackTrace(); + } finally { + if (session != null) { + session.close(); + } } } @Override public void DeleteOperation(Operation operation) { - try (Session session = sessionFactory.openSession()) { - Transaction tx = session.beginTransaction(); + Session session = null; + Transaction tx = null; + try { + session = sessionFactory.openSession(); + tx = session.beginTransaction(); session.delete(operation); tx.commit(); } catch (Exception e) { + if (tx != null) { + tx.rollback(); + } e.printStackTrace(); + } finally { + if (session != null) { + session.close(); + } } } @@ -53,7 +74,7 @@ public List FindAllOperations() { return session.createQuery("FROM Operation", Operation.class).list(); } catch (Exception e) { e.printStackTrace(); - return null; + return new ArrayList<>(); } } @@ -65,7 +86,7 @@ public List FindAllOperationsByAccountId(int id) { .getResultList(); } catch (Exception e) { e.printStackTrace(); - return null; + return new ArrayList<>(); } } -} +} \ No newline at end of file diff --git a/DataAccess/src/main/java/DAO/HibernateUserDAO.java b/DataAccess/src/main/java/DAO/HibernateUserDAO.java index d598cdc..bded311 100644 --- a/DataAccess/src/main/java/DAO/HibernateUserDAO.java +++ b/DataAccess/src/main/java/DAO/HibernateUserDAO.java @@ -21,12 +21,22 @@ public void SaveUser(User user) { if (user == null) { throw new IllegalArgumentException("Пользователь не может быть null"); } - try (Session session = sessionFactory.openSession()) { - Transaction tx = session.beginTransaction(); + Session session = null; + Transaction tx = null; + try { + session = sessionFactory.openSession(); + tx = session.beginTransaction(); session.saveOrUpdate(user); tx.commit(); } catch (Exception e) { + if (tx != null) { + tx.rollback(); + } e.printStackTrace(); + } finally { + if (session != null) { + session.close(); + } } } @@ -35,18 +45,30 @@ public void DeleteUser(User user) { if (user == null || user.getId() == null) { throw new IllegalArgumentException("Пользователь или его ID не могут быть null"); } - try (Session session = sessionFactory.openSession()) { - Transaction tx = session.beginTransaction(); + Session session = null; + Transaction tx = null; + try { + session = sessionFactory.openSession(); + tx = session.beginTransaction(); session.delete(user); tx.commit(); } catch (Exception e) { + if (tx != null) { + tx.rollback(); + } e.printStackTrace(); + } finally { + if (session != null) { + session.close(); + } } } @Override public User FindUserById(int id) { - try (Session session = sessionFactory.openSession()) { + Session session = null; + try { + session = sessionFactory.openSession(); User user = session.get(User.class, id); if (user != null) { Hibernate.initialize(user.getBankAccounts()); @@ -56,16 +78,26 @@ public User FindUserById(int id) { } catch (Exception e) { e.printStackTrace(); return null; + } finally { + if (session != null) { + session.close(); + } } } @Override public List FindAllUsers() { - try (Session session = sessionFactory.openSession()) { + Session session = null; + try { + session = sessionFactory.openSession(); return session.createQuery("FROM User", User.class).list(); } catch (Exception e) { e.printStackTrace(); return null; + } finally { + if (session != null) { + session.close(); + } } } -} +} \ No newline at end of file diff --git a/Presentation/src/test/java/BankTests.java b/Presentation/src/test/java/BankTests.java index a5b7ec8..a1b0b16 100644 --- a/Presentation/src/test/java/BankTests.java +++ b/Presentation/src/test/java/BankTests.java @@ -49,7 +49,7 @@ void setUp() { @Test void testWithdrawWithSufficientBalance() { - Double withdrawAmount = 50.0; + double withdrawAmount = 50.0; when(bankAccountService.Withdraw(bankAccount.getId(), withdrawAmount)).thenReturn(true); doNothing().when(operationService).SaveOperation(any()); @@ -62,7 +62,7 @@ void testWithdrawWithSufficientBalance() { @Test void testWithdrawWithInsufficientBalance() { - Double withdrawAmount = 150.0; + double withdrawAmount = 150.0; when(bankAccountService.Withdraw(bankAccount.getId(), withdrawAmount)).thenReturn(false); OperationResult operationResult = userController.Withdraw(bankAccount, withdrawAmount); @@ -75,7 +75,7 @@ void testWithdrawWithInsufficientBalance() { @Test void testDeposit() { - Double depositAmount = 100.0; + double depositAmount = 100.0; when(bankAccountService.Deposit(bankAccount.getId(), depositAmount)).thenReturn(true); doNothing().when(operationService).SaveOperation(any()); From 1c3402ae18274c43a6774871402df4b8ca8d64c4 Mon Sep 17 00:00:00 2001 From: Alexander Kim Date: Thu, 3 Apr 2025 10:17:54 +0300 Subject: [PATCH 4/4] fix: repaired Flyway migration --- DataAccess/src/main/resources/hibernate.cfg.xml | 2 +- Presentation/src/main/java/Presentation/Console/Main.java | 3 +++ .../src/main/resources/application.yml | 0 .../src/main/resources/db/migration/V1__init.sql | 0 .../src/main/resources/db/migration/V2__drop_tables.sql | 2 +- .../src/main/resources/db/migration/V3__init.sql | 0 6 files changed, 5 insertions(+), 2 deletions(-) rename {DataAccess => Presentation}/src/main/resources/application.yml (100%) rename {DataAccess => Presentation}/src/main/resources/db/migration/V1__init.sql (100%) rename {DataAccess => Presentation}/src/main/resources/db/migration/V2__drop_tables.sql (79%) rename {Application => Presentation}/src/main/resources/db/migration/V3__init.sql (100%) diff --git a/DataAccess/src/main/resources/hibernate.cfg.xml b/DataAccess/src/main/resources/hibernate.cfg.xml index 5e06fc0..99e6283 100644 --- a/DataAccess/src/main/resources/hibernate.cfg.xml +++ b/DataAccess/src/main/resources/hibernate.cfg.xml @@ -17,7 +17,7 @@ true true - validate + create-drop diff --git a/Presentation/src/main/java/Presentation/Console/Main.java b/Presentation/src/main/java/Presentation/Console/Main.java index 5047091..5487063 100644 --- a/Presentation/src/main/java/Presentation/Console/Main.java +++ b/Presentation/src/main/java/Presentation/Console/Main.java @@ -2,9 +2,12 @@ import Presentation.Interfaces.IMenu; +import org.flywaydb.core.Flyway; public class Main { public static void main(String[] args) { + Flyway flyway = Flyway.configure().dataSource("jdbc:postgresql://localhost:5432/JavaLabsDb", "postgres", "limosha").load(); + flyway.migrate(); IMenu menu = new Menu(); menu.Run(); } diff --git a/DataAccess/src/main/resources/application.yml b/Presentation/src/main/resources/application.yml similarity index 100% rename from DataAccess/src/main/resources/application.yml rename to Presentation/src/main/resources/application.yml diff --git a/DataAccess/src/main/resources/db/migration/V1__init.sql b/Presentation/src/main/resources/db/migration/V1__init.sql similarity index 100% rename from DataAccess/src/main/resources/db/migration/V1__init.sql rename to Presentation/src/main/resources/db/migration/V1__init.sql diff --git a/DataAccess/src/main/resources/db/migration/V2__drop_tables.sql b/Presentation/src/main/resources/db/migration/V2__drop_tables.sql similarity index 79% rename from DataAccess/src/main/resources/db/migration/V2__drop_tables.sql rename to Presentation/src/main/resources/db/migration/V2__drop_tables.sql index 82e47f8..ea5d75d 100644 --- a/DataAccess/src/main/resources/db/migration/V2__drop_tables.sql +++ b/Presentation/src/main/resources/db/migration/V2__drop_tables.sql @@ -1,4 +1,4 @@ DROP TABLE Friends; DROP TABLE Operations; DROP TABLE BankAccounts; -DROP TABLE Users; \ No newline at end of file +DROP TABLE Users; diff --git a/Application/src/main/resources/db/migration/V3__init.sql b/Presentation/src/main/resources/db/migration/V3__init.sql similarity index 100% rename from Application/src/main/resources/db/migration/V3__init.sql rename to Presentation/src/main/resources/db/migration/V3__init.sql