Search in sources :

Example 1 with IdMappingData

use of org.hibernate.envers.internal.entities.IdMappingData in project hibernate-orm by hibernate.

the class IdMetadataGenerator method addId.

@SuppressWarnings({ "unchecked" })
IdMappingData addId(PersistentClass pc, boolean audited) {
    // Xml mapping which will be used for relations
    final Element relIdMapping = new DefaultElement("properties");
    // Xml mapping which will be used for the primary key of the versions table
    final Element origIdMapping = new DefaultElement("composite-id");
    final Property idProp = pc.getIdentifierProperty();
    final Component idMapper = pc.getIdentifierMapper();
    // Checking if the id mapping is supported
    if (idMapper == null && idProp == null) {
        return null;
    }
    SimpleIdMapperBuilder mapper;
    if (idMapper != null) {
        // Multiple id
        final Class componentClass = ReflectionTools.loadClass(((Component) pc.getIdentifier()).getComponentClassName(), mainGenerator.getClassLoaderService());
        mapper = new MultipleIdMapper(componentClass, pc.getServiceRegistry());
        if (!addIdProperties(relIdMapping, (Iterator<Property>) idMapper.getPropertyIterator(), mapper, false, audited)) {
            return null;
        }
        // null mapper - the mapping where already added the first time, now we only want to generate the xml
        if (!addIdProperties(origIdMapping, (Iterator<Property>) idMapper.getPropertyIterator(), null, true, audited)) {
            return null;
        }
    } else if (idProp.isComposite()) {
        // Embedded id
        final Component idComponent = (Component) idProp.getValue();
        final Class embeddableClass = ReflectionTools.loadClass(idComponent.getComponentClassName(), mainGenerator.getClassLoaderService());
        mapper = new EmbeddedIdMapper(getIdPropertyData(idProp), embeddableClass, pc.getServiceRegistry());
        if (!addIdProperties(relIdMapping, (Iterator<Property>) idComponent.getPropertyIterator(), mapper, false, audited)) {
            return null;
        }
        // null mapper - the mapping where already added the first time, now we only want to generate the xml
        if (!addIdProperties(origIdMapping, (Iterator<Property>) idComponent.getPropertyIterator(), null, true, audited)) {
            return null;
        }
    } else {
        // Single id
        mapper = new SingleIdMapper(pc.getServiceRegistry());
        // Last but one parameter: ids are always insertable
        mainGenerator.getBasicMetadataGenerator().addBasic(relIdMapping, getIdPersistentPropertyAuditingData(idProp), idProp.getValue(), mapper, true, false);
        // null mapper - the mapping where already added the first time, now we only want to generate the xml
        mainGenerator.getBasicMetadataGenerator().addBasic(origIdMapping, getIdPersistentPropertyAuditingData(idProp), idProp.getValue(), null, true, true);
    }
    origIdMapping.addAttribute("name", mainGenerator.getVerEntCfg().getOriginalIdPropName());
    // Adding a relation to the revision entity (effectively: the "revision number" property)
    mainGenerator.addRevisionInfoRelation(origIdMapping);
    return new IdMappingData(mapper, origIdMapping, relIdMapping);
}
Also used : SingleIdMapper(org.hibernate.envers.internal.entities.mapper.id.SingleIdMapper) DefaultElement(org.dom4j.tree.DefaultElement) SimpleIdMapperBuilder(org.hibernate.envers.internal.entities.mapper.id.SimpleIdMapperBuilder) DefaultElement(org.dom4j.tree.DefaultElement) Element(org.dom4j.Element) Iterator(java.util.Iterator) PersistentClass(org.hibernate.mapping.PersistentClass) Component(org.hibernate.mapping.Component) EmbeddedIdMapper(org.hibernate.envers.internal.entities.mapper.id.EmbeddedIdMapper) Property(org.hibernate.mapping.Property) MultipleIdMapper(org.hibernate.envers.internal.entities.mapper.id.MultipleIdMapper) IdMappingData(org.hibernate.envers.internal.entities.IdMappingData)

Example 2 with IdMappingData

use of org.hibernate.envers.internal.entities.IdMappingData in project hibernate-orm by hibernate.

the class ToOneRelationMetadataGenerator method addToOne.

@SuppressWarnings({ "unchecked" })
void addToOne(Element parent, PropertyAuditingData propertyAuditingData, Value value, CompositeMapperBuilder mapper, String entityName, boolean insertable) {
    final String referencedEntityName = ((ToOne) value).getReferencedEntityName();
    final IdMappingData idMapping = mainGenerator.getReferencedIdMappingData(entityName, referencedEntityName, propertyAuditingData, true);
    final String lastPropertyPrefix = MappingTools.createToOneRelationPrefix(propertyAuditingData.getName());
    // Generating the id mapper for the relation
    final IdMapper relMapper = idMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
    // Storing information about this relation
    mainGenerator.getEntitiesConfigurations().get(entityName).addToOneRelation(propertyAuditingData.getName(), referencedEntityName, relMapper, insertable, MappingTools.ignoreNotFound(value));
    // If the property isn't insertable, checking if this is not a "fake" bidirectional many-to-one relationship,
    // that is, when the one side owns the relation (and is a collection), and the many side is non insertable.
    // When that's the case and the user specified to store this relation without a middle table (using
    // @AuditMappedBy), we have to make the property insertable for the purposes of Envers. In case of changes to
    // the entity that didn't involve the relation, it's value will then be stored properly. In case of changes
    // to the entity that did involve the relation, it's the responsibility of the collection side to store the
    // proper data.
    boolean nonInsertableFake;
    if (!insertable && propertyAuditingData.isForceInsertable()) {
        nonInsertableFake = true;
        insertable = true;
    } else {
        nonInsertableFake = false;
    }
    // Adding an element to the mapping corresponding to the references entity id's
    final Element properties = (Element) idMapping.getXmlRelationMapping().clone();
    properties.addAttribute("name", propertyAuditingData.getName());
    MetadataTools.prefixNamesInPropertyElement(properties, lastPropertyPrefix, MetadataTools.getColumnNameIterator(value.getColumnIterator()), false, insertable);
    // Extracting related id properties from properties tag
    for (Object o : properties.content()) {
        final Element element = (Element) o;
        element.setParent(null);
        parent.add(element);
    }
    // Adding mapper for the id
    final PropertyData propertyData = propertyAuditingData.getPropertyData();
    mapper.addComposite(propertyData, new ToOneIdMapper(relMapper, propertyData, referencedEntityName, nonInsertableFake));
}
Also used : PropertyData(org.hibernate.envers.internal.entities.PropertyData) Element(org.dom4j.Element) OneToOne(org.hibernate.mapping.OneToOne) ToOne(org.hibernate.mapping.ToOne) IdMapper(org.hibernate.envers.internal.entities.mapper.id.IdMapper) ToOneIdMapper(org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper) ToOneIdMapper(org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper) IdMappingData(org.hibernate.envers.internal.entities.IdMappingData)

Example 3 with IdMappingData

use of org.hibernate.envers.internal.entities.IdMappingData in project hibernate-orm by hibernate.

the class CollectionMetadataGenerator method addWithMiddleTable.

@SuppressWarnings({ "unchecked" })
private void addWithMiddleTable() {
    LOG.debugf("Adding audit mapping for property %s.%s: collection with a join table", referencingEntityName, propertyName);
    // Generating the name of the middle table
    String auditMiddleTableName;
    String auditMiddleEntityName;
    if (!StringTools.isEmpty(propertyAuditingData.getJoinTable().name())) {
        auditMiddleTableName = propertyAuditingData.getJoinTable().name();
        auditMiddleEntityName = propertyAuditingData.getJoinTable().name();
    } else {
        final String middleTableName = getMiddleTableName(propertyValue, referencingEntityName);
        auditMiddleTableName = mainGenerator.getVerEntCfg().getAuditTableName(null, middleTableName);
        auditMiddleEntityName = mainGenerator.getVerEntCfg().getAuditEntityName(middleTableName);
    }
    LOG.debugf("Using join table name: %s", auditMiddleTableName);
    // Generating the XML mapping for the middle entity, only if the relation isn't inverse.
    // If the relation is inverse, will be later checked by comparing middleEntityXml with null.
    Element middleEntityXml;
    if (!propertyValue.isInverse()) {
        // Generating a unique middle entity name
        auditMiddleEntityName = mainGenerator.getAuditEntityNameRegister().createUnique(auditMiddleEntityName);
        // Registering the generated name
        mainGenerator.getAuditEntityNameRegister().register(auditMiddleEntityName);
        middleEntityXml = createMiddleEntityXml(auditMiddleTableName, auditMiddleEntityName, propertyValue.getWhere());
    } else {
        middleEntityXml = null;
    }
    // ******
    // Generating the mapping for the referencing entity (it must be an entity).
    // ******
    // Getting the id-mapping data of the referencing entity (the entity that "owns" this collection).
    final IdMappingData referencingIdMapping = referencingEntityConfiguration.getIdMappingData();
    // Only valid for an inverse relation; null otherwise.
    String mappedBy;
    // The referencing prefix is always for a related entity. So it has always the "_" at the end added.
    String referencingPrefixRelated;
    String referencedPrefix;
    if (propertyValue.isInverse()) {
        // If the relation is inverse, then referencedEntityName is not null.
        mappedBy = getMappedBy(propertyValue.getCollectionTable(), mainGenerator.getMetadata().getEntityBinding(referencedEntityName));
        referencingPrefixRelated = mappedBy + "_";
        referencedPrefix = StringTools.getLastComponent(referencedEntityName);
    } else {
        mappedBy = null;
        referencingPrefixRelated = StringTools.getLastComponent(referencingEntityName) + "_";
        referencedPrefix = referencedEntityName == null ? "element" : propertyName;
    }
    // Storing the id data of the referencing entity: original mapper, prefixed mapper and entity name.
    final MiddleIdData referencingIdData = createMiddleIdData(referencingIdMapping, referencingPrefixRelated, referencingEntityName);
    // Creating a query generator builder, to which additional id data will be added, in case this collection
    // references some entities (either from the element or index). At the end, this will be used to build
    // a query generator to read the raw data collection from the middle table.
    final QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(mainGenerator.getGlobalCfg(), mainGenerator.getVerEntCfg(), mainGenerator.getAuditStrategy(), referencingIdData, auditMiddleEntityName, isRevisionTypeInId());
    // Adding the XML mapping for the referencing entity, if the relation isn't inverse.
    if (middleEntityXml != null) {
        // Adding related-entity (in this case: the referencing's entity id) id mapping to the xml.
        addRelatedToXmlMapping(middleEntityXml, referencingPrefixRelated, MetadataTools.getColumnNameIterator(propertyValue.getKey().getColumnIterator()), referencingIdMapping);
    }
    // ******
    // Generating the element mapping.
    // ******
    final MiddleComponentData elementComponentData = addValueToMiddleTable(propertyValue.getElement(), middleEntityXml, queryGeneratorBuilder, referencedPrefix, propertyAuditingData.getJoinTable().inverseJoinColumns(), !isLobMapElementType());
    // ******
    // Generating the index mapping, if an index exists.
    // ******
    final MiddleComponentData indexComponentData = addIndex(middleEntityXml, queryGeneratorBuilder);
    // ******
    // Generating the property mapper.
    // ******
    // Building the query generator.
    final RelationQueryGenerator queryGenerator = queryGeneratorBuilder.build(elementComponentData, indexComponentData);
    // Creating common data
    final CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(mainGenerator.getVerEntCfg(), auditMiddleEntityName, propertyAuditingData.getPropertyData(), referencingIdData, queryGenerator);
    // Checking the type of the collection and adding an appropriate mapper.
    addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
    // ******
    // Storing information about this relation.
    // ******
    storeMiddleEntityRelationInformation(mappedBy);
}
Also used : MiddleIdData(org.hibernate.envers.internal.entities.mapper.relation.MiddleIdData) RelationQueryGenerator(org.hibernate.envers.internal.entities.mapper.relation.query.RelationQueryGenerator) CommonCollectionMapperData(org.hibernate.envers.internal.entities.mapper.relation.CommonCollectionMapperData) Element(org.dom4j.Element) MiddleComponentData(org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData) IdMappingData(org.hibernate.envers.internal.entities.IdMappingData)

Example 4 with IdMappingData

use of org.hibernate.envers.internal.entities.IdMappingData in project hibernate-orm by hibernate.

the class CollectionMetadataGenerator method addIndex.

private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) {
    if (propertyValue instanceof IndexedCollection) {
        final IndexedCollection indexedValue = (IndexedCollection) propertyValue;
        final String mapKey = propertyAuditingData.getMapKey();
        if (mapKey == null) {
            // This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity.
            return addValueToMiddleTable(indexedValue.getIndex(), middleEntityXml, queryGeneratorBuilder, "mapkey", null, true);
        } else {
            final IdMappingData referencedIdMapping = mainGenerator.getEntitiesConfigurations().get(referencedEntityName).getIdMappingData();
            final int currentIndex = queryGeneratorBuilder == null ? 0 : queryGeneratorBuilder.getCurrentIndex();
            if ("".equals(mapKey)) {
                // The key of the map is the id of the entity.
                return new MiddleComponentData(new MiddleMapKeyIdComponentMapper(mainGenerator.getVerEntCfg(), referencedIdMapping.getIdMapper()), currentIndex);
            } else {
                // The key of the map is a property of the entity.
                return new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey, propertyAuditingData.getAccessType()), currentIndex);
            }
        }
    } else {
        // No index - creating a dummy mapper.
        return new MiddleComponentData(new MiddleDummyComponentMapper(), 0);
    }
}
Also used : MiddleMapKeyPropertyComponentMapper(org.hibernate.envers.internal.entities.mapper.relation.component.MiddleMapKeyPropertyComponentMapper) MiddleMapKeyIdComponentMapper(org.hibernate.envers.internal.entities.mapper.relation.component.MiddleMapKeyIdComponentMapper) MiddleDummyComponentMapper(org.hibernate.envers.internal.entities.mapper.relation.component.MiddleDummyComponentMapper) MiddleComponentData(org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData) IndexedCollection(org.hibernate.mapping.IndexedCollection) IdMappingData(org.hibernate.envers.internal.entities.IdMappingData)

Example 5 with IdMappingData

use of org.hibernate.envers.internal.entities.IdMappingData in project hibernate-orm by hibernate.

the class CollectionMetadataGenerator method addValueToMiddleTable.

/**
 * @param value Value, which should be mapped to the middle-table, either as a relation to another entity,
 * or as a simple value.
 * @param xmlMapping If not <code>null</code>, xml mapping for this value is added to this element.
 * @param queryGeneratorBuilder In case <code>value</code> is a relation to another entity, information about it
 * should be added to the given.
 * @param prefix Prefix for proeprty names of related entities identifiers.
 * @param joinColumns Names of columns to use in the xml mapping, if this array isn't null and has any elements.
 *
 * @return Data for mapping this component.
 */
@SuppressWarnings({ "unchecked" })
private MiddleComponentData addValueToMiddleTable(Value value, Element xmlMapping, QueryGeneratorBuilder queryGeneratorBuilder, String prefix, JoinColumn[] joinColumns, boolean key) {
    final Type type = value.getType();
    if (type instanceof ManyToOneType) {
        final String prefixRelated = prefix + "_";
        final String referencedEntityName = MappingTools.getReferencedEntityName(value);
        final IdMappingData referencedIdMapping = mainGenerator.getReferencedIdMappingData(referencingEntityName, referencedEntityName, propertyAuditingData, true);
        // relation isn't inverse (so when <code>xmlMapping</code> is not null).
        if (xmlMapping != null) {
            addRelatedToXmlMapping(xmlMapping, prefixRelated, joinColumns != null && joinColumns.length > 0 ? MetadataTools.getColumnNameIterator(joinColumns) : MetadataTools.getColumnNameIterator(value.getColumnIterator()), referencedIdMapping);
        }
        // Storing the id data of the referenced entity: original mapper, prefixed mapper and entity name.
        final MiddleIdData referencedIdData = createMiddleIdData(referencedIdMapping, prefixRelated, referencedEntityName);
        // And adding it to the generator builder.
        queryGeneratorBuilder.addRelation(referencedIdData);
        return new MiddleComponentData(new MiddleRelatedComponentMapper(referencedIdData), queryGeneratorBuilder.getCurrentIndex());
    } else if (type instanceof ComponentType) {
        // Collection of embeddable elements.
        final Component component = (Component) value;
        final Class componentClass = ReflectionTools.loadClass(component.getComponentClassName(), mainGenerator.getClassLoaderService());
        final MiddleEmbeddableComponentMapper componentMapper = new MiddleEmbeddableComponentMapper(new MultiPropertyMapper(), componentClass);
        final Element parentXmlMapping = xmlMapping.getParent();
        final ComponentAuditingData auditData = new ComponentAuditingData();
        final ReflectionManager reflectionManager = mainGenerator.getMetadata().getMetadataBuildingOptions().getReflectionManager();
        new ComponentAuditedPropertiesReader(ModificationStore.FULL, new AuditedPropertiesReader.ComponentPropertiesSource(reflectionManager, component), auditData, mainGenerator.getGlobalCfg(), reflectionManager, "").read();
        // Emulating first pass.
        for (String auditedPropertyName : auditData.getPropertyNames()) {
            final PropertyAuditingData nestedAuditingData = auditData.getPropertyAuditingData(auditedPropertyName);
            mainGenerator.addValue(parentXmlMapping, component.getProperty(auditedPropertyName).getValue(), componentMapper, prefix, xmlMappingData, nestedAuditingData, true, true, true);
        }
        // Emulating second pass so that the relations can be mapped too.
        for (String auditedPropertyName : auditData.getPropertyNames()) {
            final PropertyAuditingData nestedAuditingData = auditData.getPropertyAuditingData(auditedPropertyName);
            mainGenerator.addValue(parentXmlMapping, component.getProperty(auditedPropertyName).getValue(), componentMapper, referencingEntityName, xmlMappingData, nestedAuditingData, true, false, true);
        }
        // Embeddable properties may contain null values, so cannot be stored within composite primary key.
        if (propertyValue.isSet()) {
            final String setOrdinalPropertyName = mainGenerator.getVerEntCfg().getEmbeddableSetOrdinalPropertyName();
            final Element ordinalProperty = MetadataTools.addProperty(xmlMapping, setOrdinalPropertyName, "integer", true, true);
            MetadataTools.addColumn(ordinalProperty, setOrdinalPropertyName, null, null, null, null, null, null, false);
        }
        return new MiddleComponentData(componentMapper, 0);
    } else {
        // Last but one parameter: collection components are always insertable
        final boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasic(key ? xmlMapping : xmlMapping.getParent(), new PropertyAuditingData(prefix, "field", ModificationStore.FULL, RelationTargetAuditMode.AUDITED, null, null, false), value, null, true, key);
        if (mapped && key) {
            // Simple values are always stored in the first item of the array returned by the query generator.
            return new MiddleComponentData(new MiddleSimpleComponentMapper(mainGenerator.getVerEntCfg(), prefix), 0);
        } else if (mapped && !key) {
            // when mapped but not part of the key, its stored as a dummy mapper??
            return new MiddleComponentData(new MiddleMapElementNotKeyComponentMapper(mainGenerator.getVerEntCfg(), prefix), 0);
        } else {
            mainGenerator.throwUnsupportedTypeException(type, referencingEntityName, propertyName);
            // Impossible to get here.
            throw new AssertionError();
        }
    }
}
Also used : AuditedPropertiesReader(org.hibernate.envers.configuration.internal.metadata.reader.AuditedPropertiesReader) ComponentAuditedPropertiesReader(org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditedPropertiesReader) ComponentType(org.hibernate.type.ComponentType) ManyToOneType(org.hibernate.type.ManyToOneType) ReflectionManager(org.hibernate.annotations.common.reflection.ReflectionManager) MiddleSimpleComponentMapper(org.hibernate.envers.internal.entities.mapper.relation.component.MiddleSimpleComponentMapper) MiddleRelatedComponentMapper(org.hibernate.envers.internal.entities.mapper.relation.component.MiddleRelatedComponentMapper) Element(org.dom4j.Element) MultiPropertyMapper(org.hibernate.envers.internal.entities.mapper.MultiPropertyMapper) PropertyAuditingData(org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData) MiddleMapElementNotKeyComponentMapper(org.hibernate.envers.internal.entities.mapper.relation.component.MiddleMapElementNotKeyComponentMapper) ListType(org.hibernate.type.ListType) ManyToOneType(org.hibernate.type.ManyToOneType) MaterializedNClobType(org.hibernate.type.MaterializedNClobType) SetType(org.hibernate.type.SetType) MaterializedClobType(org.hibernate.type.MaterializedClobType) MapType(org.hibernate.type.MapType) ComponentType(org.hibernate.type.ComponentType) SortedSetType(org.hibernate.type.SortedSetType) SortedMapType(org.hibernate.type.SortedMapType) BagType(org.hibernate.type.BagType) Type(org.hibernate.type.Type) ComponentAuditingData(org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditingData) MiddleIdData(org.hibernate.envers.internal.entities.mapper.relation.MiddleIdData) ComponentAuditedPropertiesReader(org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditedPropertiesReader) MiddleEmbeddableComponentMapper(org.hibernate.envers.internal.entities.mapper.relation.component.MiddleEmbeddableComponentMapper) PersistentClass(org.hibernate.mapping.PersistentClass) MiddleComponentData(org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData) Component(org.hibernate.mapping.Component) IdMappingData(org.hibernate.envers.internal.entities.IdMappingData)

Aggregations

IdMappingData (org.hibernate.envers.internal.entities.IdMappingData)9 Element (org.dom4j.Element)5 PropertyData (org.hibernate.envers.internal.entities.PropertyData)4 IdMapper (org.hibernate.envers.internal.entities.mapper.id.IdMapper)4 MiddleComponentData (org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData)4 ToOneIdMapper (org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper)4 MiddleIdData (org.hibernate.envers.internal.entities.mapper.relation.MiddleIdData)3 OneToOne (org.hibernate.mapping.OneToOne)3 EntityConfiguration (org.hibernate.envers.internal.entities.EntityConfiguration)2 MultiPropertyMapper (org.hibernate.envers.internal.entities.mapper.MultiPropertyMapper)2 CommonCollectionMapperData (org.hibernate.envers.internal.entities.mapper.relation.CommonCollectionMapperData)2 MiddleRelatedComponentMapper (org.hibernate.envers.internal.entities.mapper.relation.component.MiddleRelatedComponentMapper)2 RelationQueryGenerator (org.hibernate.envers.internal.entities.mapper.relation.query.RelationQueryGenerator)2 Component (org.hibernate.mapping.Component)2 IndexedCollection (org.hibernate.mapping.IndexedCollection)2 PersistentClass (org.hibernate.mapping.PersistentClass)2 ToOne (org.hibernate.mapping.ToOne)2 BagType (org.hibernate.type.BagType)2 ComponentType (org.hibernate.type.ComponentType)2 ListType (org.hibernate.type.ListType)2