Сохранение денег в базе данных. Дизайнерское решение - PullRequest
4 голосов
/ 09 января 2009

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

class FinancialTransaction
{
    Integer txId,
    Money oldLimit,
    Money newLimit,
    Money oldBalance,
    Money newBalance,
    Date txDate
}
class Money
{   
    Currency curr,
    BigDecimal amount
}

Мой первоначальный дизайн схемы выглядит так:

CREATE TABLE tx
(
    txId bigint(20) unsigned NOT NULL,
    oldlimit_currency varchar(3) NULL,
    oldlimit_amount decimal(7,5) default 0.00,
    newlimit_currency varchar(3) NULL,
    newlimit_amount decimal(7,5) default 0.00,
    ----snipped----
    PRIMARY KEY (txId)
)

Меня волнуют две вещи:

  1. Каждая транзакция происходит на основе одной валюты. Я не задумывался над тем, нужно ли мне поддерживать транзакции, которые могут происходить в нескольких валютах. Предполагая, что это не изменится; тогда разве не более эффективно использовать один столбец валюты? Буду ли я сожалеть об этом упрощенном решении?
  2. Поскольку каждый элемент Money является ценным объектом, следует ли мне вместо этого сохранить все объекты Money в отдельную таблицу Money, а исходная таблица должна использовать moneyIds в качестве внешних ключей для таблицы Money?

То есть

CREATE TABLE tx
(
    txId bigint(20) unsigned NOT NULL,
    oldlimit_money_id int NOT NULL,
    newlimit_money_id int NOT NULL,
    ----snipped----
    PRIMARY KEY (txId),
    FOREIGN KEY (oldlimit_money_id) REFERENCES MONEY(id) ON DELETE NO ACTION ON UPDATE NO ACTION,
    FOREIGN KEY (newlimit_money_id) REFERENCES MONEY(id) ON DELETE NO ACTION ON UPDATE NO ACTION
)

Существуют ли альтернативные конструкции?

Спасибо, лентяйка.

Ответы [ 4 ]

4 голосов
/ 09 января 2009

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

CREATE TABLE tx
(
    id bigint(20) unsigned primary key,
    old_limit_currency_id int not null references CURRENCY(id),
    old_limit_value decimal(7,5) not null,
    new_limit_currency_id int not null references CURRENCY(id),
    new_limit_value decimal(7,5) not null
)

Кроме того, проверьте, достаточно ли места для ваших сценариев в десятичной системе счисления (7,5), она выглядит немного низкой. Существует старая поговорка: «Лучше быть в безопасности, чем потом сожалеть»:)

2 голосов
/ 09 января 2009

А как насчет третьей идеи:

CREATE TABLE tx
(
  txId bigint(20) unsigned NOT NULL,
  currency varchar(3) NOT NULL,
  oldlimit decimal(7,5) default 0.00,
  newlimit decimal(7,5) default 0.00,
  ----snipped----
  PRIMARY KEY (txId)
)

Все денежные значения одной транзакции должны быть в одной валюте, верно?

2 голосов
/ 09 января 2009
  1. Если в будущем вам потребуется поддерживать транзакции между двумя валютами, то должна быть возможность смоделировать это как две транзакции с одной из каждой валюты.
  2. Похоже, ваши денежные объекты семантически являются ценностями, а не сущностями. Таким образом, я не вижу необходимости выделять их как сущности.
0 голосов
/ 09 января 2009

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

...