Скрипт записи данных в поле таблицы

Существует таблица Users и таблица Balance. Связанные связью @OneToMany: один пользователь - много балансов.

Пример структуры в ответе метода введите сюда описание изображения

Что нужно? Написать скрипт-логику по следующему алгоритму:

  1. Метод получает список пользователей из БД из таблицы Users
  2. Пробегаемся по списку и получаем балансы пользователей Balance
  3. Находим записи у которых поле tax = null
  4. Записываем для таких записей поле tax = 0.20
  5. Значения где tax != null пропускаем
  6. Завершение

Часть логики которую написал но не могу закончить. Как сделать проверку по полю tax и записать данные для записей tax = null корректно? Достаточно будет примера.


public class JobUserBalance {

    private final UserService userService;
    private final UserRepo userRepo;
    private final BalanceRepo balanceRepo;
    private final BalanceService balanceService;

    public JobUserBalance(UserService userService, UserRepo userRepo, BalanceRepo balanceRepo, BalanceService balanceService) {
        this.userService = userService;
        this.userRepo = userRepo;
        this.balanceRepo = balanceRepo;
        this.balanceService = balanceService;
    }

    public void setTax() {
        Iterable<Users> users = userRepo.findAll(); // получаем список пользователей
        users.forEach(users1 -> users1.getBalance().forEach(balance -> balance.getTax())); // пробегаемся по сущности Users получаем балансы, далее поле tax
        // если значение tax у пользователя = null, то для каждой записи где null для каждого пользователя проставляем значение 0.20
        // записи где tax != null пропускаем


    }
}

таблица User

package com.example.rabbit_new2.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

@Entity
@Data
@Table(name = "users_balance")
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Users {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Column(name = "name")
    private String name;

    @NotNull
    @Column(name = "address")
    private String address;

    @NotNull
    @Column(name = "code")
    private Integer code;

    @Column(insertable = true, updatable = false)
    private LocalDateTime dateCreated;
    private LocalDateTime dateModified;



    @PrePersist
    void onCreate() {
        this.setDateCreated(LocalDateTime.now());
        this.setDateModified(LocalDateTime.now());
    }

    @PreUpdate
    void onUpdate() {
        this.setDateModified(LocalDateTime.now());
    }


    @OneToMany
    @JoinTable(
            name = "balance_calc",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "id")
    )
    private List<Balance> balance;

    @OneToOne
    @JoinTable(
            name = "data_users",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "id")
    )
    private DataUser dataUser;


}

таблица Balance

package com.example.rabbit_new2.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.*;

import java.time.LocalDateTime;

@Entity
@Table(name = "balance_calc")
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Balance {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Column(name = "name")
    private String name;

    @NotNull
    @Column(name = "sum")
    private Double sum;

    @Column(name = "tax")
    private Double tax;

    @Column(name = "result")
    private Double result;

    @Column(name = "user_id")
    private Long userId;


    @Column(insertable = true, updatable = false)
    private LocalDateTime dateCreated;
    private LocalDateTime dateModified;



    @PrePersist
    void onCreate() {
        this.setDateCreated(LocalDateTime.now());
        this.setDateModified(LocalDateTime.now());
    }

    @PreUpdate
    void onUpdate() {
        this.setDateModified(LocalDateTime.now());
    }


}

Ответы (1 шт):

Автор решения: Byb

Собственно, вот:

for (User user : users) { // проход по списку пользователей
    for (Balance balance : user.getBalances()) { // проход по списку балансов очередного пользователя
        if (balance.getTax() == null) { // если поле tax очередного баланса содержит значение null
            balance.setTax(0.2); // устанавливаем его в 0.2
            balanceService.save(balance); // сохраняем результат, чтобы он был записан в БД
        }
    }
}

Если делать при помощи forEach(), как вы пытались, то может получиться так:

users.forEach(user -> user.getBalance().forEach(balance -> {
    if (balance.getTax() == null) {
        balance.setTax(0.2);
        balanceService.save(balance);
    }
}));

Скорее всего, код можно ещё как-нибудь улучшить и сократить.


Помимо этого, хочу обратить внимание на странность в приведённом вами классе. Вы внедряете в него и репозитории, и соответствующие им сервисы. Так быть не должно. В идеале репозиторий внедряется только в одноимённый с ним сервис, а вся дальнейшая работа с сущностями в приложении осуществляется через сервисы.

Соответственно, вам должно быть достаточно внедрения userService и balanceService. Все действия, которые вы планируете делать над сущностями, должны быть покрыты этими сервисами.

И это уже не говоря о том, что решению всей этой задачи и вовсе не нужно находиться в отдельном классе. Это вполне себе работа какого-нибудь из двух упомянутых выше сервисов. Скорее даже userService-а.

Задача представляет собой смену null-поля tax балансов пользователей. Значит, вполне логично в сервисе юзеров создать метод changeNullTaxBalances(), в который и поместить приведённый в начале ответа код.

→ Ссылка