Question

I need a table to store the state of a financial transaction. The state of this transaction can be roughly modelled by this class.

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

My initial design of the schema looks like this:

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)
)

Two things worry me:

  1. Each transaction occurs based on one Currency. I haven't thought far enough as to whether I might need to support transactions that may happen in multiple currencies. Assuming that it doesn't change; then isn't it more space-efficient to just maintain one currency column ? Will I regret this simplistic solution ?
  2. Since each Money item is a value object, should I instead save all Money objects into a separate Money table and have the original table use moneyIds as foreign keys to the Money table ?

That is,

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
)

Are there alternative designs ?

Thanks lazyweb.

Was it helpful?

Solution

The currency and money value are two different concepts so would be better to separate them. There is no need to make a separate table for 'values' but would be better to have one for currencies because these are separate entities. The new design would look like:

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
)

Also, check if decimal(7,5) has enough space for your scenarios, it looks a little low. There is an old saying: "Better safe than sorry" :)

OTHER TIPS

  1. If in future you do need to support transactions between two currencies, it ought to be possible to model this as two transactions with one of each currency.
  2. It looks like your Money objects are, semantically, values rather than entities. Thus I don't see the need to separate them out as entities.

What about a third idea:

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)
)

All money values of one transaction need to be of the same currency, right?

If it's not an overkill, go one step further and store all amounts/values in a single currency and maintain an exchange rates table.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top