views:

75

answers:

1

I am trying to model such situation - there is a cash transfer (I mean a car that carries money), that has required amounts of each currency, and also an actual amount for each currency. And it seems to me pointless to create two separate classes, one for required amount and another for actual amount. So the implementation would look like this:

@Entity
public class CashTransferCurrencyAmount {
    // id, version and so on

    @Column(length = 3)
    private String currencyCode;

    @Basic
    private BigDecimal amount;

    @ManyToOne
    private CashTransfer cashTransfer;
}

@Entity
public class CashTransfer {
    // id, version and so on

    @OneToMany(mappedBy="cashTransfer")
    private Set<CashTransferCurrencyAmount> requiredCurrencyAmountSet = new HashSet<CashTransferAmountCurrency>();

    @OneToMany(mappedBy="cashTransfer")
    private Set<CashTransferCurrencyAmount> actualCurrencyAmountSet = new HashSet<CashTransferAmountCurrency>();
}

But how is a CashTransferCurrencyAmount instance to know to which collection it belongs? I have two ideas:

1 - add a discriminator field to CashTransferCurrencyAmount:

public enum RequestType {
    ACTUAL,
    REQUIRED
}

@Basic
@Enumerated(EnumType.STRING)
private RequestType requestType;

and add @WHERE annotations to collections in CashTransfer. This is preferable for me.

2 - create two join tables. one for mapping requested amounts and one for mapping actual amounts. I dislike this one as I don't want too many tables in my DB.

Are there any other ways to achieve this? I this approach correct?
And please don't tell me to put both requested and actual amounts in one entity. The real case is more complicated, each CashTransferCurrencyAmount has it's own collections so it can't be solved that way.

EDIT
As for requests for complete story - there used to be two values in CashTransferCurrencyAmount - required (I think it should be 'requested') and actual, but now each amount has it's own collection - how this amount is split into denominations. So I need a collection of amounts, each one having a collection of denominations. The type of CurrencyAmount and CurencyDenomination seems to be the same for requested ones and for actual ones.

+1  A: 

Since you want CashTransferCurrencyAmount instance to know which collection it belongs to, I assume you want to have some logic based on that. The way I would model your situation would be using inheritance.

You're saying "it seems to me pointless to create two separate classes", I would however try to convince you that you should. You could use a "Single Table" inheritance type, so that you don't introduce additional tables in your DB, which is what you're trying to accomplish.

My shot would look something like:


@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "request_type", discriminatorType = DiscriminatorType.STRING)
public abstract class CashTransferCurrencyAmount {
    // id, version and so on

    @Column(length = 3)
    private String currencyCode;

    @Basic
    private BigDecimal amount;

    @ManyToOne
    private CashTransfer cashTransfer;
}

@Entity
@DiscriminatorValue("REQUIRED")
public class CashTransferCurrencyAmountRequired extends CashTransferCurrencyAmount {
    // required anount specific stuff here
}

@Entity
@DiscriminatorValue("ACTUAL")
public class CashTransferCurrencyAmountActual extends CashTransferCurrencyAmount {
    // actual anount specific stuff here
}

@Entity
public class CashTransfer {
    // id, version and so on

    @OneToMany(mappedBy="cashTransfer")
    private Set requiredCurrencyAmountSet = new HashSet();

//Stackoverflow deleting my generic sets! But it's exactly the same as in your code...

    @OneToMany(mappedBy="cashTransfer")
    private Set actualCurrencyAmountSet = new HashSet();
}
Michal Bachman
I wasn't precise enough. I should have written "How is Hibernate to know to which collection put each CashTransferCurrencyAmount". The instances are the same. But the idea with subclasses in single table is interesting. At least Hibernate will do this discrimination work by itself.
Tadeusz Kopec
I finally decided to use a discriminator and where clause, but I like your answer and it's the only one, so I accept it.
Tadeusz Kopec