Example usage for org.hibernate.persister.collection OneToManyPersister getKeyColumnNames

List of usage examples for org.hibernate.persister.collection OneToManyPersister getKeyColumnNames

Introduction

In this page you can find the example usage for org.hibernate.persister.collection OneToManyPersister getKeyColumnNames.

Prototype

@Override
    public String[] getKeyColumnNames() 

Source Link

Usage

From source file:to.etc.domui.hibernate.model.CriteriaCreatingVisitor.java

License:Open Source License

/**
 * Child-related subquery: determine existence of children having certain characteristics. Because
 * the worthless Hibernate "meta model" API and the utterly disgusting way that mapping data is
 * "stored" in Hibernate we resort to getting the generic type of the child property's collection
 * to determine the type where the subquery is executed on.
 * @see to.etc.webapp.query.QNodeVisitorBase#visitExistsSubquery(to.etc.webapp.query.QExistsSubquery)
 *//*from   w ww. ja v a  2 s . c  o m*/
@Override
public void visitExistsSubquery(QExistsSubquery<?> q) throws Exception {
    String parentAlias = getCurrentAlias();
    Class<?> parentBaseClass = q.getParentQuery().getBaseClass();
    PropertyMetaModel<?> pmm = MetaManager.getPropertyMeta(parentBaseClass, q.getParentProperty());

    //-- If we have a dotted name it can only be parent.parent.parent.childList like (with multiple parents). Parse all parents.
    String childListProperty = q.getParentProperty();
    int ldot = childListProperty.lastIndexOf('.');
    if (ldot != -1) {
        //-- Join all parents, and get the last parent's reference and name
        String last = parseSubcriteria(childListProperty, true); // Create the join path;
        String parentpath = childListProperty.substring(0, ldot); // This now holds parent.parent.parent
        childListProperty = childListProperty.substring(ldot + 1); // And this childList

        //-- We need a "new" parent class: the class that actually contains the "child" list...
        PropertyMetaModel<?> parentpm = MetaManager.getPropertyMeta(parentBaseClass, parentpath);
        parentBaseClass = parentpm.getActualType();

        //-- The above join will have created another alias to the joined table; this is the first part of the "last" reference (which is alias.property).
        ldot = last.indexOf('.');
        if (ldot < 0)
            throw new IllegalStateException("Invalid result from parseSubcriteria inside exists.");
        parentAlias = last.substring(0, ldot);
    }

    //-- Should be List type
    if (!List.class.isAssignableFrom(pmm.getActualType()))
        throw new ProgrammerErrorException("The property '" + q.getParentQuery().getBaseClass() + "."
                + q.getParentProperty() + "' should be a list (it is a " + pmm.getActualType() + ")");

    //-- Make sure there is a where condition to restrict
    QOperatorNode where = q.getRestrictions();
    //      if(where == null)
    //         throw new ProgrammerErrorException("exists subquery has no restrictions: " + this);

    //-- Get the list's generic compound type because we're unable to get it from Hibernate easily.
    Class<?> coltype = MetaManager.findCollectionType(pmm.getGenericActualType());
    if (coltype == null)
        throw new ProgrammerErrorException("The property '" + q.getParentQuery().getBaseClass() + "."
                + q.getParentProperty() + "' has an undeterminable child type");

    //-- 2. Create an exists subquery; create a sub-statement
    DetachedCriteria dc = DetachedCriteria.forClass(coltype, nextAlias());
    Criterion exists = Subqueries.exists(dc);
    dc.setProjection(Projections.id()); // Whatever: just some thingy.

    //-- Append the join condition; we need all children here that are in the parent's collection. We need the parent reference to use in the child.
    ClassMetadata childmd = m_session.getSessionFactory().getClassMetadata(coltype);

    //-- Entering the crofty hellhole that is Hibernate meta"data" 8-(

    ClassMetadata parentmd = m_session.getSessionFactory().getClassMetadata(parentBaseClass);
    int index = findMoronicPropertyIndexBecauseHibernateIsTooStupidToHaveAPropertyMetaDamnit(parentmd,
            childListProperty);
    if (index == -1)
        throw new IllegalStateException(
                "Hibernate does not know property '" + childListProperty + " in " + parentmd.getEntityName());
    Type type = parentmd.getPropertyTypes()[index];
    CollectionType bt = (CollectionType) type;
    final OneToManyPersister persister = (OneToManyPersister) ((SessionFactoryImpl) m_session
            .getSessionFactory()).getCollectionPersister(bt.getRole());
    String[] keyCols = persister.getKeyColumnNames();

    //-- Try to locate those FK column names in the FK table so we can fucking locate the mapping property.
    String childupprop = findCruddyChildProperty(childmd, keyCols);
    if (childupprop == null)
        throw new IllegalStateException("Cannot find child's parent property in crufty Hibernate metadata: "
                + Arrays.toString(keyCols));

    //-- Well, that was it. What a sheitfest. Add the join condition to the parent
    dc.add(Restrictions.eqProperty(childupprop + "." + childmd.getIdentifierPropertyName(),
            parentAlias + "." + parentmd.getIdentifierPropertyName()));

    //-- Sigh; Recursively apply all parts to the detached thingerydoo
    Object old = m_currentCriteria;
    Class<?> oldroot = m_rootClass;
    Map<String, String> oldAliases = m_aliasMap;
    m_aliasMap = new HashMap<String, String>();

    m_rootClass = q.getBaseClass();
    checkHibernateClass(m_rootClass);
    m_currentCriteria = dc;
    if (where != null)
        where.visit(this);
    if (m_last != null) {
        dc.add(m_last);
        m_last = null;
    }
    m_aliasMap = oldAliases;
    m_currentCriteria = old;
    m_rootClass = oldroot;
    m_last = exists;
}