Object Oriented Design for generic hibernate object

I'm currently working good object oriented principles, and hibernate, I have this POJO, in which the properties would be dynamically populated. This is a design pattern I've read for good Object Oriented Design, in which it would be easy to add attributes to specificic object without breaking the application. My question is, how can you map this to a table, when your attributes is supposedly dynamic, I'm using an enum to limit the key value pairs for the map, but ideally it can still grow. I am only using in-memory database (h2) and I'm not going to be using the code for production use. This is for learning purposes only. see code below:

public class Transaction {

    private static Map<Object, Object> properties;

    public Transaction(){
        if(null != properties)
            properties = new LinkedHashMap<Object, Object>();
    }

    public Transaction(Map<Object, Object> properties){
        if(null != properties)
            setProperties(properties);
    }

    public void setProperties(Map<Object, Object> prop){
        properties = prop;
    }
    public void setProperties(Properties property, String value){
        properties.put(property, value);
    }

    public Map<Object, Object> getProperties(){
        return properties;
    }

    public String getProperties(Properties property){
        return (String) properties.get(property);
    }


}

So I want to be able to create a table that would have this properties, dynamically, My Enum:

public enum Properties {
    Entry("Entry"), Id("Entry_ID"), Name("Name"), Credit("Credit");

    private final String description;

    private Properties(final String description){
        this.description = description;
    }
    @Override
    public String toString(){
        return description;
    }
}

I have this hibernate mapping, but as you can see this would be need to be updated everytime a field is updated, I need a generic mapping so that when I change/add the attributes, annotation or xml would be okay, see below:

 <class name="Transaction" table="TRANSACTION">
    <id name="id" column="ENTRY_ID">
        <generator class="increment"/>
    </id>
    <property name="name"/>
     <property name="credit" type="boolean" column="IS_CREDIT"/>
</class>

Answers


UserDefinedField on Marin Fowler's web site may be a perfect starting point for exploring general answers to this question.

As for Hibernate: It's really designed for statically binding tables to objects and you may have significant problems if you change the schema while running. You can implement the following solutions, though:

  • Serialized LOB (you serialize your Map into a binary field or - using JSON/XML - a text field). This is a half-and-half approach - half tabular/normal form/SQL and half not-SQL. So, if this approach is attractive, you might want to consider going all-in with a NoSQL database as discussed later
  • Attribute table, where your customized attributes are stored in a key-value pair table that joins to to the master table. This can be mapped in Hibernate using Indexed Collections (see section 7.2.2.2 Maps) and you would end up with something quite like in your question:

    @Entity 
    public class Transaction {
    
        @Id @GeneratedValue public Integer getId() { return id; }
        public void setId(Integer id) { this.id = id; }
        private Integer id;
    
        // ... snip ...
    
        @OneToMany(mappedBy="transaction")
        @MapKey(name="name")
        public Map<String, String> getProperties(){
        return properties;
        }
        public void setProperties(Map<String, String> prop){
        properties = prop;
        }
        private Map<String, String> properties; // NB: Type has to be <String, String> because the column name is a String and you have defined the property value to be a String.
    
        public void setProperty(Properties property, String value){
        properties.put(property, value);
        }
        public String getProperty(String name){
        return (String) properties.get(property);
        }
    }
    
    @Entity
    public class Property {
        @Id @GeneratedValue public Integer getId() { return id; }
        public void setId(Integer id) { this.id = id; }
        private Integer id;
    
        @ManyToOne
        public Transaction getTransaction() { return transaction; }
        public void setTransaction(Transaction transaction) { this.transaction = transaction; }
        private Transaction transaction;
    
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        private String name;
    
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        private String description;
    
    }
    
  • Pre-defined custom-fields, where you start with a really wide table with loads of unused columns. In this implementation you end up defining a mapping between your arbitrary property names and the pre-defined column names (getString1(), getString10(), etc)

However, a much better solution for you may be to use a NoSQL database - specifically a document-based one. These allow you to store and retrieve arbitrary data-structures (maps and lists). Interestingly, using such an approach makes binding to the data store significantly easier.

MongoDB or Redis (Java bindings at Jedis) are examples.


Need Your Help

Dead code identification (C++)

c++ static-analysis dead-code

I have a large legacy C++ project compiled under Visual Studio 2008. I know there is a reasonably amount of 'dead' code that is not accessed anywhere -- methods that are not called, whole classes ...

How to show button after typing text

javascript jquery html css jsp

i want to show button on the form after typing something inside input element in Jsp.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.