0

私は現在、優れたオブジェクト指向の原則に取り組んでおり、休止状態になっています。プロパティが動的に入力されるこのPOJOがあります。これは、アプリケーションを壊すことなく特定のオブジェクトに属性を簡単に追加できる優れたオブジェクト指向設計について私が読んだ設計パターンです。私の質問は、属性が動的であると思われる場合、これをテーブルにどのようにマップできるかです。列挙型を使用してマップのキーと値のペアを制限していますが、理想的にはまだ大きくなる可能性があります。私はメモリ内データベース (h2) のみを使用しており、本番環境でコードを使用するつもりはありません。これは学習のみを目的としています。以下のコードを参照してください。

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);
    }


}

したがって、このプロパティを持つテーブルを動的に作成できるようにしたいのですが、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;
    }
}

私はこの休止状態のマッピングを持っていますが、ご覧のとおり、フィールドが更新されるたびにこれを更新する必要があります。属性、注釈、または xml を変更/追加するときに問題がないように、一般的なマッピングが必要です。以下を参照してください。

 <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>
4

1 に答える 1

2

Marin Fowler の Web サイトのUserDefinedFieldは、この質問に対する一般的な回答を調べるための出発点として最適です。

Hibernate に関しては、実際にはテーブルをオブジェクトに静的にバインドするように設計されており、実行中にスキーマを変更すると重大な問題が発生する可能性があります。ただし、次のソリューションを実装できます。

  • シリアル化されたLOB (マップをバイナリ フィールドにシリアル化するか、JSON/XML を使用してテキスト フィールドにシリアル化します)。これは、表形式/標準形式/SQL の半分と非 SQL の半分という半分ずつのアプローチです。したがって、このアプローチが魅力的である場合は、後で説明するように、NoSQL データベースにオールインすることを検討することをお勧めします。
  • 属性テーブル。カスタマイズした属性は、マスター テーブルに結合するキーと値のペア テーブルに格納されます。これは、インデックス付きコレクションを使用して Hibernate でマップできます(セクション 7.2.2.2 マップを参照)。

    @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;
    
    }
    
  • 事前定義された custom-fields。未使用の列がたくさんある非常に幅の広いテーブルから始めます。この実装では、任意のプロパティ名と事前定義された列名 ( 、 など) の間のマッピングを定義することになりgetString1()ますgetString10()

ただし、NoSQL データベース、特にドキュメントベースのデータベースを使用する方が、はるかに優れたソリューションになる場合があります。これらを使用すると、任意のデータ構造 (マップとリスト) を格納および取得できます。興味深いことに、このようなアプローチを使用すると、データ ストアへのバインドが大幅に簡単になります。

MongoDBまたはRedis ( Jedisでの Java バインディング) が例です。

于 2013-08-05T10:11:08.273 に答える