简体   繁体   中英

What's a good database design for hierarchical data versioning with Hibernate?

I need to store a history of changes for hierarchical data. The data is a one-to-many relation: a setting entity has many properties. Here are my tables:

Setting
------------------------------
Id            INTEGER NOT NULL
CompanyId     INTEGER NOT NULL
Name          TEXT NOT NULL


SettingProperty
------------------------------
SettingId            INTEGER NOT NULL
PropertyName         TEXT NOT NULL

I'm using Hibernate as the ORM, the corresponding Java entity would look somewhat like this

public class Setting {

    private int id;
    private int companyId;
    private String name;

    private Set<String> properties;
    // ....
}

Now, whenever the setting name changes or a property is added to the setting, I need to store the full history of changes. I also need to easily query the historical setting for a given point in time. I've taken into account multiple different options, ie:

  1. adding into the 'Setting' table a 'ChangeDate' column (tells us when the given setting version was modified) and a 'CommonId' column (tells us which entities form the history of a single setting in time - ie in case when the name changes the new setting version has a new name and a new id so we need to way to tell that this is just a new version of the same setting). This is simple and should work but makes querying for most current data hard (ie SELECT * FROM Setting WHERE ChangeDate = (SELECT MAX(ChangeDate ...))
  2. having a table with just an Id, a BLOB (for keeping the whole serialized Java Setting object) and a ChangeDate. This way I'm fine with just one table, but I'm in big trouble when I want to add/remove something into the Setting object because I need to update the already saved objects.
  3. having for each of the above tables a separate History table (with same columns and a ChangeDate) - this makes it easy to query for current data (just use the regular tables) but maintaining a few tables with almost identical schema is some minor pain.

Any suggestions or better ideas? Please keep in mind that I'm using Hibernate so not all SQL query quirks are possible. My DB is PostgreSQL.

Eventually we decided to use Hibernate Envers because it does al the work for us

So we'll use whatever mapping tables it generates for us :)

I don't have experience with history tables, but this might help:

First, I would suggest having your friendly neighborhood DBA review your database schema. Although I'm not a DBA, here are a few suggestions:

Setting
        settingID           long not null, primary key
        companyID           long not null, foreign key to Company table
        name                varchar(255) not null, unique

SettingProperty
        settingPropertyID   long not null, primary key
        settingID           long not null, foreign key to Setting table
        name                varchar(255) not null, unique

Company
        companyID           long not null, primary key
        name                varchar(255) not null, unique
        abbr                varchar(50), unique


Notes: 
       0: primary keys are always named with the table name followed by 'ID'.
       1: Table names begin with a capital letter
       2: column names begin with a lower case letter
       3: primary keys are to have no business meaning        
       4: primary and foreign keys are long and not int 
       to ensure the max value isn't likely to be reached.
       5: I suggest you consider calling your tables something 
       more meaningful than Setting and SettingProperty (assuming
       there is such a meaning).
       6: Consider adding company abbreviation to your Company 
       table (abbr), which can be null, but must be unique.
       7:Don't add columns to the database tables being audited
         with auditing information. They should be ignorant of the fact
         they are being audited.
       8: Use database triggers to update a history table when a record
         is updated, inserted, or deleted. Don't do it in Java.
       9: Search Google for 'store historical data in database triggers' or similar search
          on how to best create a history table.
         Example:
       https://www.google.com/#q=storing+historical+data+in+database+triggers&start=10
       10: There is a column with not null and unique, and another with nullable and unique.
         Some databases don't like nullable and unique (it treats more than one null in the 
         column as violating the unique rule). 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM