All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.api.database.DatabaseSession Maven / Gradle / Ivy

There is a newer version: 5.1
Show newest version
/*
 * Sonar, open source software quality management tool.
 * Copyright (C) 2009 SonarSource SA
 * mailto:contact AT sonarsource DOT com
 *
 * Sonar is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * Sonar 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 Sonar; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package org.sonar.api.database;

import org.apache.commons.lang.StringUtils;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

/**
 * @since 1.10
 */
public class DatabaseSession implements BatchExtension {

  // IMPORTANT : this value must be the same than the property
  // hibernate.jdbc.batch_size from /META-INF/persistence.xml :
  public static final int BATCH_SIZE = 100;

  private final DatabaseConnector connector;
  private EntityManager entityManager = null;
  private int index = 0;
  private boolean inTransaction = false;

  public DatabaseSession(DatabaseConnector connector) {
    this.connector = connector;
  }

  public EntityManager getEntityManager() {
    return entityManager;
  }

  public void start() {
    entityManager = connector.createEntityManager();
    index = 0;
  }

  public void stop() {
    commit();
    if (entityManager != null && entityManager.isOpen()) {
      entityManager.clear();
      entityManager.close();
      entityManager = null;
    }
  }

  public void commit() {
    if (entityManager != null && inTransaction) {
      if (entityManager.isOpen()) {
        if (entityManager.getTransaction().getRollbackOnly()) {
          entityManager.getTransaction().rollback();
        } else {
          entityManager.getTransaction().commit();
        }
      }
      inTransaction = false;
      index = 0;
    }
  }

  public void rollback() {
    if (entityManager != null && inTransaction) {
      entityManager.getTransaction().rollback();
      inTransaction = false;
      index = 0;
    }
  }

  public  T save(T model) {
    startTransaction();
    internalSave(model, true);
    return model;
  }

  public Object saveWithoutFlush(Object model) {
    startTransaction();
    internalSave(model, false);
    return model;
  }

  public boolean contains(Object model) {
    startTransaction();
    return entityManager.contains(model);
  }

  public void save(Object... models) {
    startTransaction();
    for (Object model : models) {
      save(model);
    }
  }

  private void internalSave(Object model, boolean flushIfNeeded) {
    entityManager.persist(model);
    if (flushIfNeeded && (++index % BATCH_SIZE == 0)) {
      flush();
    }
  }

  public Object merge(Object model) {
    startTransaction();
    return entityManager.merge(model);
  }

  public void remove(Object model) {
    startTransaction();
    entityManager.remove(model);
    if (++index % BATCH_SIZE == 0) {
      flush();
    }
  }

  public  T reattach(Class entityClass, Object primaryKey) {
    startTransaction();
    return entityManager.getReference(entityClass, primaryKey);
  }

  private void startTransaction() {
    if (!inTransaction) {
      entityManager.getTransaction().begin();
      inTransaction = true;
    }
  }

  private void flush() {
    entityManager.flush();
    entityManager.clear();
  }

  public Query createQuery(String hql) {
    startTransaction();
    return entityManager.createQuery(hql);
  }

  public  T getSingleResult(Query query, T defaultValue) {
    try {
      return (T) query.getSingleResult();
    } catch (NoResultException ex) {
      return defaultValue;
    }
  }

  public  T getEntity(Class entityClass, Object id) {
    startTransaction();
    return getEntityManager().find(entityClass, id);
  }

  public  T getSingleResult(Class entityClass, Object... criterias) {
    try {
      return getSingleResult(getQueryForCriterias(entityClass, true, criterias), (T) null);
    } catch (NonUniqueResultException ex) {
      LoggerFactory.getLogger(DatabaseSession.class).warn("NonUniqueResultException on entity {} with criterias : {}",
          entityClass.getSimpleName(), StringUtils.join(criterias, ","));
      throw ex;
    }
  }

  public  List getResults(Class entityClass, Object... criterias) {
    return getQueryForCriterias(entityClass, true, criterias).getResultList();
  }

  public  List getResults(Class entityClass) {
    return getQueryForCriterias(entityClass, false, null).getResultList();
  }

  private Query getQueryForCriterias(Class entityClass, boolean raiseError, Object... criterias) {
    if (criterias == null && raiseError) {
      throw new IllegalStateException("criterias parameter must be provided");
    }
    startTransaction();
    StringBuilder hql = new StringBuilder("SELECT o FROM ").append(entityClass.getSimpleName()).append(" o");
    if (criterias != null) {
      hql.append(" WHERE ");
      Map mappedCriterias = new HashMap();
      for (int i = 0; i < criterias.length; i += 2) {
        mappedCriterias.put((String) criterias[i], criterias[i + 1]);
      }
      buildCriteriasHQL(hql, mappedCriterias);
      Query query = getEntityManager().createQuery(hql.toString());

      for (Map.Entry entry : mappedCriterias.entrySet()) {
        query.setParameter(entry.getKey(), entry.getValue());
      }
      return query;
    }
    return getEntityManager().createQuery(hql.toString());
  }

  private void buildCriteriasHQL(StringBuilder hql, Map mappedCriterias) {
    for (Iterator i = mappedCriterias.keySet().iterator(); i.hasNext();) {
      String criteria = i.next();
      hql.append("o.").append(criteria).append("=:").append(criteria);
      if (i.hasNext()) {
        hql.append(" AND ");
      }
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy