ch.systemsx.cisd.openbis.generic.server.dataaccess.db.AbstractDAO.java Source code

Java tutorial

Introduction

Here is the source code for ch.systemsx.cisd.openbis.generic.server.dataaccess.db.AbstractDAO.java

Source

/*
 * Copyright 2007 ETH Zuerich, CISD
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import net.sf.beanlib.hibernate3.Hibernate3SequenceGenerator;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import ch.rinn.restrictions.Private;
import ch.systemsx.cisd.common.collections.CollectionStyle;
import ch.systemsx.cisd.common.collections.CollectionUtils;
import ch.systemsx.cisd.common.collections.IToStringConverter;
import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;

/**
 * Abstract super class of all <i>Hibernate</i> DAOs.
 * 
 * @author Christian Ribeaud
 */
public abstract class AbstractDAO extends HibernateDaoSupport {

    /** The original source database instance. */
    private DatabaseInstancePE databaseInstance;

    protected AbstractDAO(final SessionFactory sessionFactory, final DatabaseInstancePE databaseInstance) {
        assert sessionFactory != null : "Unspecified session factory";
        assert databaseInstance != null || this instanceof DatabaseInstanceDAO : "Unspecified "
                + "database instance (only permitted for DatabaseInstancesDAO).";
        setDatabaseInstance(databaseInstance);
        setSessionFactory(sessionFactory);
    }

    /**
     * Validates given <i>Persistence Entity</i> using an appropriate {@link ClassValidator}.
     */
    @SuppressWarnings("unchecked")
    protected final static <E> void validatePE(final E pe) throws DataIntegrityViolationException {
        validatePE(pe, new ClassValidator(pe.getClass()));
    }

    /**
     * Validates given <i>Persistence Entity</i> using the given {@link ClassValidator}.
     */
    protected final static <E> void validatePE(final E pe, final ClassValidator<E> validator)
            throws DataIntegrityViolationException {
        final InvalidValue[] validationMessages = validator.getInvalidValues(pe);
        if (validationMessages.length > 0) {
            throw new DataIntegrityViolationException(
                    CollectionUtils.abbreviate(validationMessages, -1, new IToStringConverter<InvalidValue>() {
                        //
                        // IToStringConverter
                        //

                        public final String toString(final InvalidValue value) {
                            return String.format(value.getMessage(), value.getValue());
                        }
                    }, CollectionStyle.NO_BOUNDARY));
        }
    }

    @Private
    public final void setDatabaseInstance(final DatabaseInstancePE databaseInstance) {
        this.databaseInstance = databaseInstance;
    }

    /**
     * Returns home database instance.
     */
    public final DatabaseInstancePE getDatabaseInstance() {
        return databaseInstance;
    }

    /**
     * Casts given <var>list</var> to specified type.
     * <p>
     * The purpose of this method is to avoid <code>SuppressWarnings("unchecked")</code> in calling
     * methods.
     * </p>
     */
    @SuppressWarnings("unchecked")
    protected static final <T> List<T> cast(final List list) {
        return list;
    }

    /**
     * Ensures that given {@link List} contains one and only one entity.
     * 
     * @throws EmptyResultDataAccessException if given <var>entities</var> are <code>null</code> or
     *             empty.
     * @throws IncorrectResultSizeDataAccessException if more than one entity is found in given
     *             {@link List}.
     */
    @SuppressWarnings("unchecked")
    protected final static <T> T getEntity(final List<T> entities) throws DataAccessException {
        return (T) DataAccessUtils.requiredSingleResult(entities);
    }

    /**
     * Casts given <var>entity</var> to specified type.
     * 
     * @throws EmptyResultDataAccessException if given <var>entity</var> is <code>null</code>.
     */
    @SuppressWarnings("unchecked")
    protected final static <T> T getEntity(final Object entity) throws EmptyResultDataAccessException {
        if (entity == null) {
            throw new EmptyResultDataAccessException(1);
        }
        return (T) entity;
    }

    /**
     * Casts given <var>entityOrNull</var> to specified type or returns null for null input.
     */
    @SuppressWarnings("unchecked")
    protected final static <T> T tryGetEntity(final Object entityOrNull) {
        return entityOrNull == null ? null : (T) entityOrNull;
    }

    /**
     * Checks given <var>entities</var> and throws a {@link IncorrectResultSizeDataAccessException}
     * if it contains more than one item.
     * 
     * @return <code>null</code> or the entity found at index <code>0</code>.
     */
    protected final static <T> T tryFindEntity(final List<T> entities, final String entitiesName,
            final Object... parameters) throws IncorrectResultSizeDataAccessException {
        final int size = entities.size();
        switch (size) {
        case 0:
            return null;
        case 1:
            return entities.get(0);
        default:
            throw new IncorrectResultSizeDataAccessException(
                    String.format("%d %s found for '%s'. Expected: 1 or 0.", size, entitiesName,
                            parameters.length == 1 ? parameters[0] : Arrays.asList(parameters)),
                    1, size);
        }
    }

    /**
     * Executes given <var>sql</var>.
     * <p>
     * Should be an <code>INSERT</code> or <code>UPDATE</code> statement.
     * </p>
     */
    protected final void executeUpdate(final String sql, final Serializable... parameters) {
        getHibernateTemplate().execute(new HibernateCallback() {

            //
            // HibernateCallback
            //

            public final Object doInHibernate(final Session session) throws HibernateException, SQLException {
                final SQLQuery sqlQuery = session.createSQLQuery(sql);
                for (int i = 0; i < parameters.length; i++) {
                    Serializable parameter = parameters[i];
                    if (parameter instanceof Long) {
                        sqlQuery.setLong(i, (Long) parameter);
                    } else if (parameter instanceof Integer) {
                        sqlQuery.setInteger(i, (Integer) parameter);
                    } else if (parameter instanceof Character) {
                        sqlQuery.setCharacter(i, (Character) parameter);
                    } else if (parameter instanceof Date) {
                        sqlQuery.setDate(i, (Date) parameter);
                    } else {
                        sqlQuery.setSerializable(i, parameter);
                    }
                }
                sqlQuery.executeUpdate();
                return null;
            }
        });
    }

    /**
     * Natively performs given <var>sql</var> and returns an unique result by calling
     * {@link Query#uniqueResult()}.
     */
    @SuppressWarnings("unchecked")
    protected final <T> T getUniqueResult(final String sql, final Object... parameters) {
        return (T) getHibernateTemplate().execute(new HibernateCallback() {

            //
            // HibernateCallback
            //

            public final Object doInHibernate(final Session session) {
                return session.createSQLQuery(String.format(sql, parameters)).uniqueResult();
            }
        });
    }

    protected final static Object[] toArray(final Object... objects) {
        return objects;
    }

    protected final long getNextSequenceId(String sequenceName) {
        return Hibernate3SequenceGenerator.nextval(sequenceName, getSession(true));
    }

}