001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.gps.device.jpa.indexer;
018:
019: import java.util.List;
020: import javax.persistence.Query;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.apache.openjpa.persistence.OpenJPAEntityManager;
025: import org.apache.openjpa.persistence.OpenJPAPersistence;
026: import org.apache.openjpa.persistence.OpenJPAQuery;
027: import org.apache.openjpa.persistence.jdbc.FetchDirection;
028: import org.apache.openjpa.persistence.jdbc.JDBCFetchPlan;
029: import org.apache.openjpa.persistence.jdbc.LRSSizeAlgorithm;
030: import org.apache.openjpa.persistence.jdbc.ResultSetType;
031: import org.compass.core.CompassSession;
032: import org.compass.gps.device.jpa.EntityManagerWrapper;
033: import org.compass.gps.device.jpa.JpaGpsDevice;
034: import org.compass.gps.device.jpa.JpaGpsDeviceException;
035: import org.compass.gps.device.jpa.embedded.openjpa.CompassProductDerivation;
036: import org.compass.gps.device.jpa.entities.EntityInformation;
037: import org.compass.gps.device.support.parallel.IndexEntity;
038:
039: /**
040: * OpenJPA indexer that uses fetch plan to scroll the result set and index it. Performs
041: * better than JPA <code>setFirstResult</code> and <code>setMaxResults</code> especially
042: * for large result sets.
043: *
044: * @author kimchy
045: */
046: public class OpenJPAJpaIndexEntitiesIndexer implements
047: JpaIndexEntitiesIndexer {
048:
049: private static final Log log = LogFactory
050: .getLog(OpenJPAJpaIndexEntitiesIndexer.class);
051:
052: private JpaGpsDevice jpaGpsDevice;
053:
054: public void setJpaGpsDevice(JpaGpsDevice jpaGpsDevice) {
055: this .jpaGpsDevice = jpaGpsDevice;
056: }
057:
058: public void performIndex(CompassSession session,
059: IndexEntity[] entities) {
060: for (IndexEntity indexEntity : entities) {
061: EntityInformation entityInformation = (EntityInformation) indexEntity;
062: if (jpaGpsDevice.isFilteredForIndex(entityInformation
063: .getName())) {
064: continue;
065: }
066: int fetchCount = jpaGpsDevice.getFetchCount();
067: if (!jpaGpsDevice.isRunning()) {
068: return;
069: }
070: EntityManagerWrapper wrapper = jpaGpsDevice
071: .getEntityManagerWrapper().newInstance();
072: try {
073: wrapper.open();
074: OpenJPAEntityManager entityManager = OpenJPAPersistence
075: .cast(wrapper.getEntityManager());
076: entityManager.setPopulateStoreCache(false);
077: if (log.isDebugEnabled()) {
078: log.debug(jpaGpsDevice
079: .buildMessage("Indexing entities ["
080: + entityInformation.getName()
081: + "] using query ["
082: + entityInformation
083: .getQueryProvider() + "]"));
084: }
085: Query query = entityInformation.getQueryProvider()
086: .createQuery(entityManager, entityInformation);
087: OpenJPAQuery openJPAQuery = OpenJPAPersistence
088: .cast(query);
089: JDBCFetchPlan fetch = (JDBCFetchPlan) openJPAQuery
090: .getFetchPlan();
091: if (CompassProductDerivation.isReleasedVersion()) {
092: doSetFetchPlan(fetchCount, fetch);
093: }
094: List results = openJPAQuery.getResultList();
095: for (Object item : results) {
096: session.create(item);
097: entityManager.evict(item);
098: session.evictAll();
099: }
100: entityManager.clear();
101: wrapper.close();
102: } catch (Exception e) {
103: log.error(jpaGpsDevice
104: .buildMessage("Failed to index the database"),
105: e);
106: wrapper.closeOnError();
107: if (!(e instanceof JpaGpsDeviceException)) {
108: throw new JpaGpsDeviceException(
109: jpaGpsDevice
110: .buildMessage("Failed to index the database"),
111: e);
112: }
113: throw (JpaGpsDeviceException) e;
114: }
115: }
116: }
117:
118: private void doSetFetchPlan(int fetchCount, JDBCFetchPlan fetch) {
119: fetch.setFetchBatchSize(fetchCount);
120: fetch.setResultSetType(ResultSetType.SCROLL_INSENSITIVE);
121: fetch.setFetchDirection(FetchDirection.FORWARD);
122: fetch.setLRSSizeAlgorithm(LRSSizeAlgorithm.UNKNOWN);
123: }
124: }
|