Search code examples
databaserelational-databaseprimary-keysql2o

Mapping Object fields that do not contain a unique identifier in a relational database


I have an object of type Reward that is a field within a Card class. I am attempting to store the Card class within the database. The other fields within Card are not a problem for database persistence, so for brevity we will only concern ourselves with the Reward field within a Card.

Here is the Reward class. For brevity, getters/setters have been removed.

public class Reward {
private RewardType rewardType;
//Value should be 1 for weapons
private int amount;
//Null unless RewardType is weapon
private WeaponData weaponData;

public Reward() {
}

public Reward(RewardType rewardType, int amount) {
    if (rewardType == RewardType.WEAPON) {
        throw new IllegalArgumentException("A weapon must contain a non-null WeaponData field");
    }
    this.rewardType = rewardType;
    this.amount = amount;
}

public static class WeaponData {
    private int attack;
    private int durability;

    public WeaponData(int attack, int durability) {
        this.attack = attack;
        this.durability = durability;
    }

    public int getAttack() {
        return attack;
    }

    public void setAttack(int attack) {
        this.attack = attack;
    }

    public int getDurability() {
        return durability;
    }

    public void setDurability(int durability) {
        this.durability = durability;
    }
}

}

The issue I am coming across on when trying to map this object that resides within the Card class into the database is that a Reward is not naturally a unique entity, thus it does not contain an id. It is simply a set of Card properties that have been bundled up into a single class.

The only solution I have come up with so far is to not have foreign keys to the Reward in the database, and instead denormalize all of the Reward fields to be placed within the Cards table.

So for example, the Cards table will contain the reward_type, amount, and weapon_data columns instead of a foreign key to a reward.

I asked my friends about this method and they mentioned that it was denormalized, so it would not be an elegant solution.

I would also have issues mapping this using my thin JDBC wrapper named Sql2o, as it would be unable to help me map the objects to the database tables in a smooth manner.

I have considered switching some of my database tables to a NoSql database which would make this situation much easier, since the objects would be easily mapped to JSON documents and stored within the database.

However, it does pose some large issues since other tables within my database contain foreign key references to the Cards table.

If anyone has a solution to map these Reward objects in a clean manner to a database, all help would be greatly appreciated.

Thank you for reading this.


Solution

  • I solved this using Hibernate ORM. Marking a field as @Embedded and its type as @Embeddable solved the problem.

    It seems that the solution was to simply place the fields that do not contain an identifier within the containing table, or embed them.

    For collections, this is more complex and pseudo-ids need to be generated in order to persist the entity, but this another topic.