Search code examples
javaspringspring-datamappingspring-data-jdbc

Persisting Money with Spring Data JDBC


Let's take a following entity:

class Item{
    @Id
    Long id;
    String name;
    org.joda.money.Money price;
}

and a corresponding repository:

interface ItemRepository extends CrudRepository<Item, Long> {
}

Is it possible to persist Item in a relational DB table having amount and currency in separate columns without manually rewriting SQL queries offered by ItemRepository?

DDL could be something like:

CREATE TABLE ITEM (
    ID             INTEGER IDENTITY NOT NULL,
    NAME           VARCHAR(255)     NULL,
    PRICE_AMOUNT   DECIMAL          NULL,
    PRICE_CURRENCY VARCHAR(3)       NULL
);

Storing Money in a single VARCHAR column using custom @WritingConverter and @ReadingConverter is the closest I got, however this is not an option, as I need amount and currency clearly separated at the DB level.

I'm fine with replacing joda.money in favor of javax.money if that makes a difference, however I do not want to introduce my own custom type for handling money in domain layer.


Solution

  • There are the following options available to persist properties of non standard types in Spring Data JDBC

    1. Use @WritingConverter and @ReadingConverter in order to convert the value to something Spring Data JDBC knows. You already discovered that this works only with single columns

    2. You can mark it as an @Embedded which will convert each attribute to a column. I'm not sure if Money has suitable attributes but it is lacking a suitable constructor so this doesn't work either.

    3. Use a different type that you can handle with one of the first approaches. In this case this would mean write your own Money type which has a suitable constructor and attributes to work as an embedded.

    4. Tweak your database: you can create a view which uses a single column representation and stores it as a single column. It might still make it available as separate columns for sorting and filtering.