Как я могу выполнить итерацию по объектам, которые уже находятся в базе данных, и обновить поле?

#database #rest #webapi

#База данных #rest #webapi

Вопрос:

Я создаю RESTful API, который покажет все мои активы / инвестиции. Я хочу показать в каждом активе, сколько процентов от общей стоимости portolio составляет этот актив. Я хочу, чтобы totalValue было чем-то динамическим, поэтому с каждым новым созданным активом он добавляет (realTimePrice * amount) к totalValue.

Мой вопрос: как только я закончил заполнять базу данных и вычислено общее значение, как я могу запустить для каждого объекта в базе данных и запустить setPercentage() ?

Например:

«имя»: биткойн «тикер»: BTC-USD «процент»: 20

Как суммируется totalValue с каждым объектом, вставленным в базу данных

введите описание изображения здесь

Вот как я заполняю свою базу данных:

 package assets.asset;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration

class SeedDB {

@Bean
CommandLineRunner initDatabase(DataBase repository) {
    return args -> {

        repository.save(new Asset("", "",, , "Crypto"));
        repository.save(new Asset("", "",, , "Crypto"));
        repository.save(new Asset("", "",, , "Crypto"));
        repository.save(new Asset("", "",, , "Stock"));
        repository.save(new Asset("", "",, , "Stock"));
        repository.save(new Asset("", "",, , "Stock"));
        
    };
}

}
  

Ответ №1:

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

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

Это значение, которое должно вычисляться по запросу.

Мы могли бы сохранить определенное значение в базе данных под названием «Общая стоимость активов». Это будет содержать соответствующую информацию. Затем каждый раз, когда выполняется операция по добавлению нового номера, у нас может быть служба, которая будет выполнять

 public void setTotalValue() {
    TotalValue =BigDecimal.valueOf(amount);
    repository.save(totalValue); // this line can be however you want to persist your data
}
  

Идея состоит в том, чтобы добавлять к общему значению каждый раз, когда вы добавляете новый ресурс, а затем, когда мы хотим вычислить общее значение, мы можем сделать что-то вроде,

 public Map<Asset, BigDecimal> getTotalPercentages(List<Asset> assets) {
    for (asset : asset) {
        map.put(asset, asset.value/totalValue);
    }
    return map;
}
  

Это даст вам точные данные динамически и сэкономит дополнительное время для вставки в БД.

РЕДАКТИРОВАТЬ: после того, как в комментариях был указан некоторый контекст, я переделал другое решение.

Мы могли бы просто иметь переменную totalValue, которая растет каждый раз, когда вы добавляете актив на этапе заполнения, и в конце заполнения вы могли бы выполнить итерацию по всем активам и установить процент для каждого из них.

 int totalValue = 0;
String[] types = new String[]{"Crypto", "Stock"};
for (int i = 0; i < NUM_OF_DESIRED_ASSETS; i  ) {
    Random r = new Random();
    int value = r.nextInt(10);
    int index = r.nextInt(2);
    repository.save(new Asset("", "",value, , types[index]));   

    totalValue =value; 
}

for (asset : assets) {
    asset.setPercentage(asset.value/totalValue);
    repository.save(asset);
}

  

Комментарии:

1. Спасибо за ответ 🙂 Я согласен, что это не масштабируемый дизайн, но максимальное количество ресурсов, которые я должен хранить, составляет 50-70. » каждый раз, когда мы добавляем один ресурс, нам нужно будет обновлять процент для всех значений. » — Я хочу вычислить totalValue после того, как все активы были вставлены, а затем запустить все активы и использовать setPercentage(), который должен будет использовать totalValue после того, как он уже был вычислен. » Это значение, которое должно вычисляться по запросу. » Я подумал об этом, есть ли способ создать GET of (/assets/percentage) и выполнить этот setPercentage() ?

2. конечно, это правильно — вариант 1, у вас может быть GET endpoint /assets / totalValue, который извлекает общую стоимость всех активов. затем в вашем интерфейсе вы могли бы выполнить вычисление amount / totalValue . вариант 2 — получить активы / процент / {asset_id}, как вы упомянули, и отправить идентификатор актива. Затем вычислите процент на серверной части и верните его. лично вариант 1 звучит лучше, поскольку вычисление действительно может быть выполнено клиентом или сервером, и мы экономим на одном поиске в БД для получения информации об активе. хотя и то, и другое работает!

3. Спасибо за ответ. Я все еще не понимаю, как мне это реализовать. Я хочу, чтобы в моем RestController, когда пользователи будут запрашивать активы / процент, он запускал setPercentage для всех активов.

4. Я все еще думаю, что лучший способ сделать это — использовать класс SeedDB после создания всех объектов и установки totalValue, тогда мне нужно каким-то образом запустить setPercentage() для всех объектов, которые уже есть в базе данных. Я еще раз скажу, я знаю, что это не оптимально, но я просто собираюсь использовать максимум 50-70 ресурсов и буду блокировать методы публикации пользователей, чтобы они не могли добавлять ресурсы только мне, они могут только смотреть.

5. контекст немного проясняет ситуацию, спасибо за это — отредактировал мой ответ, чтобы включить новый подход. надеюсь, это имеет смысл.

Ответ №2:

Ответ из «Берлина» очень помог. Как только я закончил заполнять базу данных, я просто добавил следующее в класс SeedDB :

             for (Asset asset : repository.findAll())
            {
            asset.percentage = asset.setPercentage();
            repository.save(asset);
            }
  

Я пробовал несколько идей, в том числе пытался использовать @PutMapping, который запускает setPercentage(), но не понимал, как выполнить это для всех ресурсов, собрать их и вернуть.

В любом случае проблема решена 🙂