/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat, Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.search.query.hibernate.impl;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.search.util.impl.HibernateHelper;
import org.hibernate.search.util.logging.impl.Log;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.search.SearchException;
import org.hibernate.search.query.engine.spi.EntityInfo;
import org.hibernate.search.util.logging.impl.LoggerFactory;
/**
* @author Emmanuel Bernard
* @author Hardy Ferentschik
*/
public class ObjectLoaderHelper {
private static final Log log = LoggerFactory.make();
public static Object load(EntityInfo entityInfo, Session session) {
Object maybeProxy = executeLoad( entityInfo, session );
try {
HibernateHelper.initialize( maybeProxy );
}
catch ( RuntimeException e ) {
if ( LoaderHelper.isObjectNotFoundException( e ) ) {
log.debugf(
"Object found in Search index but not in database: %s with id %s",
entityInfo.getClazz(), entityInfo.getId()
);
session.evict( maybeProxy );
maybeProxy = null;
}
else {
throw e;
}
}
return maybeProxy;
}
public static List returnAlreadyLoadedObjectsInCorrectOrder(EntityInfo[] entityInfos, Session session) {
//mandatory to keep the same ordering
List result = new ArrayList( entityInfos.length );
for ( EntityInfo entityInfo : entityInfos ) {
//FIXME This call is very inefficient when @Entity's id property is different
//FIXME from Document stored id as we need to do the actual query again
Object element = executeLoad( entityInfo, session );
if ( element != null && HibernateHelper.isInitialized( element ) ) {
//all existing elements should have been loaded by the query,
//the other ones are missing ones
result.add( element );
}
else {
if ( log.isDebugEnabled() ) {
log.debugf(
"Object found in Search index but not in database: %s with %s",
entityInfo.getClazz(), entityInfo.getId()
);
}
}
}
return result;
}
private static Object executeLoad(EntityInfo entityInfo, Session session) {
Object maybeProxy;
if ( areDocIdAndEntityIdIdentical( entityInfo, session ) ) {
//be sure to get an initialized object but save from ONFE and ENFE
maybeProxy = session.load( entityInfo.getClazz(), entityInfo.getId() );
}
else {
Criteria criteria = session.createCriteria( entityInfo.getClazz() );
criteria.add( Restrictions.eq( entityInfo.getIdName(), entityInfo.getId() ) );
try {
maybeProxy = criteria.uniqueResult();
}
catch ( HibernateException e ) {
//FIXME should not raise an exception but return something like null
//FIXME this happens when the index is out of sync with the db)
throw new SearchException(
"Loading entity of type " + entityInfo.getClazz().getName() + " using '"
+ entityInfo.getIdName()
+ "' as document id and '"
+ entityInfo.getId()
+ "' as value was not unique"
);
}
}
return maybeProxy;
}
//TODO should we cache that result?
public static boolean areDocIdAndEntityIdIdentical(EntityInfo entityInfo, Session session) {
String hibernateIdentifierProperty = session.getSessionFactory()
.getClassMetadata( entityInfo.getClazz() )
.getIdentifierPropertyName();
return entityInfo.getIdName().equals( hibernateIdentifierProperty );
}
}