Hibernate's dynamic-component?

Romsl

Erfahrenes Mitglied
Hi,

bin auf der Suche in Hibernate dynamisch (zur Laufzeit) Attribute einzufügen, bzw. zu einer Klasse hinzuzufügen.
Habe in der Hibernate Doku das Tag dynamic-component gefunden, aber leider ist die Beschreibung hierfür wahrlich keine Meisterleistung.

Sollte es jemand schonmal erfolgreich getestet haben würde ich mich über einen Post sehr freuen.

Die neuen Attribute sollen persistent in einer Datenbank gehalten werden.

Danke
 
Hi,

ich hab mal was hinbekommen, falls es irgend jemanden mal interessieren sollte.

cfg ist die Hibernate Configuration.

Code:
        try {

            // The "sql" data types.
            Type type = new StringType();

            //Type dynamicType = new DynamicComponentType(new String[]{"bar"}, new Type[]{type}, new int[]{-1}, new Cascades.CascadeStyle[]{Cascades.STYLE_NONE});

            //Type dynamicType = new DynamicComponentType(new String[]{"foo", "bar"}, new Type[]{type, type}, new int[]{-1}, new Cascades.CascadeStyle[]{Cascades.STYLE_NONE, Cascades.STYLE_NONE});


            Type dynamicType = new DynamicComponentType(new String[]{"foo", "bar", "tender"},
                    new Type[]{type, type, type}, new int[]{-1},
                    new Cascades.CascadeStyle[]{Cascades.STYLE_NONE, Cascades.STYLE_NONE, Cascades.STYLE_NONE});


            // The persistent dynamic attribute.
            PersistentClass persistentClass = cfg.createMappings().getClass(Dynamic.class);
            Property dynamicProperty = persistentClass.getProperty("dynamicAttributes");

            // Get the dynamic component and
            Component dynamicComponent = (Component) dynamicProperty.getValue();

            dynamicComponent.setType(dynamicType);

            // Add the new attribute if the component is a dynamic component.
            if (dynamicComponent.isDynamic()) {
                dynamicComponent.addProperty(addDynamicAttribute("foo", type, persistentClass));
                dynamicComponent.addProperty(addDynamicAttribute("bar", type, persistentClass));
                dynamicComponent.addProperty(addDynamicAttribute("tender", type, persistentClass));
            }

            // Database schema update.
            try {
                //sessionFactoryBean.updateDatabaseSchema();
                new SchemaUpdate(cfg).execute(true, true);
            }
            catch (HibernateException he) {
                he.printStackTrace();
            }
        }
        catch (MappingException me) {
            me.printStackTrace();
        }

die append Methode

Code:
    private Property addDynamicAttribute(String name, Type type, PersistentClass persistentClass) {

        // Create a new db column specification.
        Column column = new Column();
        column.setName(name.toUpperCase());
        column.setType(type);

        // Add column to table also.
        persistentClass.getTable().addColumn(column);

        // Create a simple value that contains the column and will be set to the property as information.
        SimpleValue simpleValue = new SimpleValue(persistentClass.getTable());
        simpleValue.addColumn(column);
        simpleValue.setType(type);

        // Create a new property.
        Property property = new Property();
        property.setName(name);
        property.setPropertyAccessorName("property");
        property.setCascade("none");
        property.setValue(simpleValue);

        return property;
    }

und hier ein Beispielmapping.

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<!--
    The dynmic test mapping.

    @author Romsl
 -->

<hibernate-mapping>

    <class name="bo.Dynamic" table="Z_DYNAMIC_COMPONENT">

        <id name="id" type="long" unsaved-value="-1">
            <column name="ID" not-null="true"/>
            <generator class="native"/>
        </id>

        <property name="name" type="string">
            <column name="NAME" not-null="true"/>
        </property>

        <dynamic-component name="dynamicAttributes"/>

    </class>

</hibernate-mapping>

Viel Spaß damit,

Romsl
 
Hallo,

das obige Beispiel funktioniert sehr gut bei Hibernate 2.x , bei Hibernate 3.x scheint aber setType deprecated zu sein. Hat jemand so etwas schon mit Hibernate 3.x gemacht?
 
Ja, hier.

Hibernate Mapping:

Code:
<hibernate-mapping>

    <class name="bo.Dynamic" table="Z_DYNAMIC_COMPONENT">

        <id name="id" type="long" unsaved-value="-1">
            <column name="ID" not-null="true"/>
            <generator class="native"/>
        </id>

        <property name="name" type="string">
            <column name="NAME" not-null="true"/>
        </property>

        <dynamic-component name="dynamicAttributes"/>

    </class>

</hibernate-mapping>

DynamicAttribute:

Code:
package bo;

import java.io.Serializable;

/**
 * The <code>DynamicAttribute</code> contains informations about a dynamic attribute and the business
 * object to which it belongs to.
 * <p/>
 *
 * @author Romsl
 */
public class DynamicAttribute implements Serializable {

    /**
     * The default property name of the "dynamic-component".
     */
    public static final String DEFAULT_PROPERTY_NAME = "dynamicAttributes";

    /**
     * The default property accessor name.
     */
    public static final String DEFAULT_PROPERTY_ACCESSOR_NAME = "property";

    /**
     * The default length of the specific database.
     */
    public static final int DEFAULT_DATABASE_LENGTH = -1;

    /**
     * The default cascading of the dynamic attribute.
     */
    public static final String DEFAULT_CASCADE = "none";

    /**
     * The persistent id of the <code>DynamicAttribute</code> object.
     */
    private Long id;

    /**
     * The persistent class which this dynamic attribute belongs to.
     */
    private Class persistentClass;

    /**
     * The property name of the "dynamic-component" element in the mapping of the persistent
     * class. The default value is "dynamicAttributes".
     */
    private String propertyName = DEFAULT_PROPERTY_NAME;

    /**
     * The name of the dynamic attribute. This name is also the header of the database
     * column.
     */
    private String name;

    /**
     * The <code>Type</code> <code>Class</code> of the dynamic attribute.
     */
    private Class typeClass;

    /**
     * The property accessor name is a information about how to get access to the property.
     * The default property accessor name is "property".
     */
    private String propertyAccessorName = DEFAULT_PROPERTY_ACCESSOR_NAME;

    /**
     * Whether the dynamic attribute is requrired or not. The default nullable value is
     * false.
     */
    private boolean nullable = false;

    /**
     * Whether the value of this dynamic attribute have to be unique. The default unique value
     * is false.
     */
    private boolean unique = false;

    /**
     * The length of the dynamic attribute. The default is the default database length.
     */
    private int length = DEFAULT_DATABASE_LENGTH;

    /**
     * The cascading of the dynamic attribute. The default cascading is "none".
     */
    private String cascade = DEFAULT_CASCADE;

    /**
     * Returns the persistent id of the <code>DynamicAttribute</code> object.
     *
     * @return The persistent id of the <code>DynamicAttribute</code> object.
     */
    public Long getId() {
        return id;
    }

    /**
     * Sets the persistent id of the <code>DynamicAttribute</code> object.
     *
     * @param id The persistent id of the <code>DynamicAttribute</code> object.
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Returns the persistent class which this dynamic attribute belongs to.
     *
     * @return The persistent class which this dynamic attribute belongs to.
     */
    public Class getPersistentClass() {
        return persistentClass;
    }

    /**
     * Sets the persistent class which this dynamic attribute belongs to.
     *
     * @param persistentClass The persistent class which this dynamic attribute belongs to.
     */
    public void setPersistentClass(Class persistentClass) {
        this.persistentClass = persistentClass;
    }

    /**
     * Returns the property name of the "dynamic-component" element in the mapping of the
     * persistent class. The default value is "dynamicAttributes".
     *
     * @return The property name of the "dynamic-component" element in the mapping of the
     *         persistent class.
     */
    public String getPropertyName() {
        return propertyName;
    }

    /**
     * Sets the property name of the "dynamic-component" element in the mapping of the
     * persistent class. The default value is "dynamicAttributes".
     *
     * @param propertyName The property name of the "dynamic-component" element in the
     *                     mapping of the persistent class.
     */
    public void setPropertyName(String propertyName) {
        this.propertyName = propertyName;
    }

    /**
     * Returns the name of the dynamic attribute. This name is also the header of the database
     * column.
     *
     * @return The name of the dynamic attribute. This name is also the header of the database
     *         column.
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the name of the dynamic attribute. This name is also the header of the database
     * column.
     *
     * @param name The name of the dynamic attribute. This name is also the header of the
     *             database column.
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Returns the <code>Type</code> <code>Class</code> of the dynamic attribute.
     *
     * @return The <code>Type</code> <code>Class</code> of the dynamic attribute.
     */
    public Class getTypeClass() {
        return typeClass;
    }

    /**
     * Sets the <code>Type</code> <code>Class</code> of the dynamic attribute.
     *
     * @param typeClass The <code>Type</code> <code>Class</code> of the dynamic attribute.
     */
    public void setTypeClass(Class typeClass) {
        this.typeClass = typeClass;
    }

    /**
     * Returns the property accessor name is a information about how to get access to the
     * property. The default property accessor name is "property".
     *
     * @return The property accessor name is a information about how to get access to the
     *         property.
     */
    public String getPropertyAccessorName() {
        return propertyAccessorName;
    }

    /**
     * Sets the property accessor name is a information about how to get access to the
     * property. The default property accessor name is "property".
     *
     * @param propertyAccessorName The property accessor name is a information about how
     *                             to get access to the property.
     */
    public void setPropertyAccessorName(String propertyAccessorName) {
        this.propertyAccessorName = propertyAccessorName;
    }

    /**
     * Returns whether the dynamic attribute is requrired or not. The default nullable
     * value is false.
     *
     * @return Whether the dynamic attribute is requrired or not.
     */
    public boolean isNullable() {
        return nullable;
    }

    /**
     * Sets whether the dynamic attribute is requrired or not. The default nullable value
     * is false.
     *
     * @param nullable Whether the dynamic attribute is requrired or not.
     */
    public void setNullable(boolean nullable) {
        this.nullable = nullable;
    }

    /**
     * Returns whether the value of this dynamic attribute have to be unique. The default
     * unique value is false.
     *
     * @return Whether the value of this dynamic attribute have to be unique.
     */
    public boolean isUnique() {
        return unique;
    }

    /**
     * Sets whether the value of this dynamic attribute have to be unique. The default unique
     * value is false.
     *
     * @param unique Whether the value of this dynamic attribute have to be unique.
     */
    public void setUnique(boolean unique) {
        this.unique = unique;
    }

    /**
     * Returns the length of the dynamic attribute. The default is the default database length.
     *
     * @return The length of the dynamic attribute. The default is the default database length.
     */
    public int getLength() {
        return length;
    }

    /**
     * Sets the length of the dynamic attribute. The default is the default database length.
     *
     * @param length The length of the dynamic attribute. The default is the default database
     *               length.
     */
    public void setLength(int length) {
        this.length = length;
    }

    /**
     * Returns the cascading of the dynamic attribute. The default cascading is "none".
     *
     * @return The cascading of the dynamic attribute.
     */
    public String getCascade() {
        return cascade;
    }

    /**
     * Sets the cascading of the dynamic attribute. The default cascading is "none".
     *
     * @param cascade The cascading of the dynamic attribute.
     */
    public void setCascade(String cascade) {
        this.cascade = cascade;
    }
}

Code:
      // Dieses wurde aus der DB geladen.           
                 DynamicAttribute dynamicAttribute = (DynamicAttribute) i.next();

                 // The persistent dynamic attribute.
                 PersistentClass persistentClass = cfg.getClassMapping(dynamicAttribute.getPersistentClass().getName());
                 Property dynamicProperty = persistentClass.getProperty(dynamicAttribute.getPropertyName());

                 // Get the dynamic component and
                 Component dynamicComponent = (Component) dynamicProperty.getValue();

                 // Add the new attribute if the component is a dynamic component.
                 if (dynamicComponent.isDynamic()) {
                     dynamicComponent.addProperty(addDynamicAttribute(dynamicAttribute, persistentClass));
                 }

Code:
    private Property addDynamicAttribute(DynamicAttribute dynamicAttribute, PersistentClass persistentClass) {

        // Create a new db column specification.
        Column column = new Column();
        column.setName(dynamicAttribute.getName().toUpperCase());
        column.setNullable(dynamicAttribute.isNullable());
        column.setUnique(dynamicAttribute.isUnique());

        int length = dynamicAttribute.getLength();
        if (length != DynamicAttribute.DEFAULT_DATABASE_LENGTH) {
            column.setLength(length);
        }

        // Add column to table also.
        persistentClass.getTable().addColumn(column);

        // Create a simple value that contains the column and will be set to the property as information.
        SimpleValue simpleValue = new SimpleValue(persistentClass.getTable());
        simpleValue.addColumn(column);
        simpleValue.setTypeName(dynamicAttribute.getTypeClass().getName());

        // Create a new property.
        Property property = new Property();
        property.setName(dynamicAttribute.getName());
        property.setNodeName(dynamicAttribute.getName());
        property.setPropertyAccessorName(dynamicAttribute.getPropertyAccessorName());
        property.setCascade(dynamicAttribute.getCascade());
        property.setValue(simpleValue);

        return property;
    }
 
Danke,

damit hast Du mir sehr geholfen. Ich kenne mich recht gut mit Spring aus, kann hier also als Gegenleistung auf Fragen antworten :-))

Viele Grüße aus Hannover,

Andreas Bednarz
 
Zurück