com.nortal.petit.orm.StatementSupport.java Source code

Java tutorial

Introduction

Here is the source code for com.nortal.petit.orm.StatementSupport.java

Source

/**
 *   Copyright 2014 Nortal AS
 *
 *   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 com.nortal.petit.orm;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.persistence.PersistenceException;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.nortal.petit.beanmapper.BeanMapping;
import com.nortal.petit.orm.persist.BeanHandler;
import com.nortal.petit.orm.persist.CollectionPersistMethods;
import com.nortal.petit.orm.persist.CollectionPersistUtil;
import com.nortal.petit.orm.persist.ItemHandler;
import com.nortal.petit.orm.relation.RelationLoader;
import com.nortal.petit.orm.relation.RelationMapper;
import com.nortal.petit.orm.relation.RelationUtil;
import com.nortal.petit.orm.statement.DeleteStatement;
import com.nortal.petit.orm.statement.InsertStatement;
import com.nortal.petit.orm.statement.LoadStatement;
import com.nortal.petit.orm.statement.QueryStatement;
import com.nortal.petit.orm.statement.StatementBuilder;
import com.nortal.petit.orm.statement.UpdateStatement;
import com.nortal.petit.orm.statement.clause.Where;
import com.nortal.petit.orm.statement.clause.WherePart;

/**
 * Support class for statement APIs.
 * 
 * @author Alrik Peets
 * @author Aleksei Lissitsin
 */
public class StatementSupport {

    private StatementConfiguration statementConfiguration;

    public StatementSupport(StatementConfiguration statementConfiguration) {
        this.statementConfiguration = statementConfiguration;
    }

    private JdbcTemplate getJdbcTemplate() {
        return statementConfiguration.getJdbcTemplate();
    }

    private StatementBuilder getStatementBuilder() {
        return statementConfiguration.getStatementBuilder();
    }

    // Insert methods

    /**
     * Creates insert statement by bean class
     * 
     * @param beanClass
     *            Bean class
     * @return {@link InsertStatement}
     */
    public <B> InsertStatement<B> insertStmForType(Class<B> beanClass) {
        return new InsertStatement<B>(getJdbcTemplate(), getStatementBuilder(), beanClass);
    }

    /**
     * Creates insert statement by bean
     * 
     * @param bean
     *            Bean to insert
     * @return {@link InsertStatement}
     */
    @SuppressWarnings("unchecked")
    public <B> InsertStatement<B> insertStm(B bean) {
        return insertStm(Arrays.asList(bean));
    }

    /**
     * Creates insert statement by beans
     * 
     * @param beans
     *            Beans to insert
     * @return {@link InsertStatement}
     */
    public <B> InsertStatement<B> insertStm(Collection<B> beans) {
        return new InsertStatement<B>(getJdbcTemplate(), getStatementBuilder(), (B[]) beans.toArray());
    }

    /**
     * Inserts bean by primary key mapping
     * 
     * @param bean
     *            Bean to insert
     */
    @SuppressWarnings("unchecked")
    public <B> void insert(B bean) {
        if (bean == null) {
            return;
        }
        insert(Arrays.asList(bean));
    }

    /**
     * Inserts beans by primary key mapping
     * 
     * @param beans
     *            Beans to insert
     */
    public <B> void insert(Collection<B> beans) {
        if (CollectionUtils.isEmpty(beans)) {
            return;
        }
        insertStm(beans).exec();
    }

    // Update methods

    /**
     * Creates update statement by bean class
     * 
     * @param beanClass
     *            Bean class
     * @return {@link UpdateStatement}
     */
    public <B> UpdateStatement<B> updateStm(Class<B> beanClass) {
        return new UpdateStatement<B>(getJdbcTemplate(), getStatementBuilder(), beanClass);
    }

    /**
     * Creates update statement by bean
     * 
     * @param bean
     *            Bean to update
     * @return {@link UpdateStatement}
     */
    @SuppressWarnings("unchecked")
    public <B> UpdateStatement<B> updateStm(B bean) {
        return updateStm(Arrays.asList(bean));
    }

    /**
     * Creates update statement by beans
     * 
     * @param beans
     *            Beans to update
     * @return {@link UpdateStatement}
     */
    public <B> UpdateStatement<B> updateStm(Collection<B> beans) {
        return new UpdateStatement<B>(getJdbcTemplate(), getStatementBuilder(), (B[]) beans.toArray());
    }

    /**
     * Updates bean by primary key mapping
     * 
     * @param bean
     *            Bean to update
     */
    @SuppressWarnings("unchecked")
    public <B> void update(B bean) {
        if (bean == null) {
            return;
        }
        update(Arrays.asList(bean));
    }

    /**
     * Updates beans by primary key mapping
     * 
     * @param beans
     *            Beans to update
     */
    public <B> void update(Collection<B> beans) {
        if (CollectionUtils.isEmpty(beans)) {
            return;
        }

        UpdateStatement<B> stm = new UpdateStatement<B>(getJdbcTemplate(), getStatementBuilder(),
                (B[]) beans.toArray());
        if (stm.getMapping().id() != null) {
            stm.exec();
        } else {
            throw new PersistenceException("Model " + beans.iterator().next().getClass().getSimpleName()
                    + " does not have primary key mapping");
        }
    }

    // Delete methods

    /**
     * Creates delete statement by bean class
     * 
     * @param beanClass
     *            Bean class
     * @return {@link DeleteStatement}
     */
    public <B> DeleteStatement<B> deleteStm(Class<B> beanClass) {
        return new DeleteStatement<B>(getJdbcTemplate(), getStatementBuilder(), beanClass);
    }

    /**
     * Creates delete statement by bean
     * 
     * @param bean
     *            Bean to delete
     * @return {@link DeleteStatement}
     */
    @SuppressWarnings("unchecked")
    public <B> DeleteStatement<B> deleteStm(B bean) {
        return deleteStm(Arrays.asList(bean));
    }

    /**
     * Creates delete statement by beans
     * 
     * @param beans
     *            Beans to delete
     * @return {@link DeleteStatement}
     */
    public <B> DeleteStatement<B> deleteStm(Collection<B> beans) {
        return new DeleteStatement<B>(getJdbcTemplate(), getStatementBuilder(), (B[]) beans.toArray());
    }

    /**
     * Deletes bean by primary key mapping
     * 
     * @param bean
     *            Bean to deleted
     */
    @SuppressWarnings("unchecked")
    public <B> void delete(B bean) {
        if (bean == null) {
            return;
        }
        delete(Arrays.asList(bean));
    }

    /**
     * Deletes beans by primary key mapping
     * 
     * @param beans
     *            Beans to deleted
     */
    public <B> void delete(Collection<B> beans) {
        if (CollectionUtils.isEmpty(beans)) {
            return;
        }

        DeleteStatement<B> stm = new DeleteStatement<B>(getJdbcTemplate(), getStatementBuilder(),
                (B[]) beans.toArray());
        if (stm.getMapping().id() != null) {
            stm.exec();
        } else {
            throw new PersistenceException("Model " + beans.iterator().next().getClass().getSimpleName()
                    + " does not have primary key mapping");
        }
    }

    // Load methods

    /**
     * Creates load statement by bean class
     * 
     * @param beanClass
     *            Bean class
     * @return {@link LoadStatement}
     */
    public <B> LoadStatement<B> loadStm(Class<B> beanClass) {
        return new LoadStatement<B>(getJdbcTemplate(), getStatementBuilder(), beanClass);
    }

    /**
     * Loads bean by primary key mapping
     * 
     * @param beanClass
     *            Bean class
     * @param id
     *            Primary key value
     * @return Bean
     */
    public <B> B loadById(Class<B> beanClass, Object id) {
        Assert.notNull(id, "id is mandatory");

        LoadStatement<B> stm = loadStm(beanClass);
        BeanMapping<B> mapping = stm.getMapping();
        if (mapping.id() != null) {
            stm.where(mapping.id().name(), id);
        } else {
            throw new PersistenceException("Model " + mapping + " does not have primary key mapping");
        }
        return stm.single();
    }

    private class Methods<B> implements CollectionPersistMethods<B> {
        @Override
        public void insert(Collection<B> beans) {
            StatementSupport.this.insert(beans);
        }

        @Override
        public void update(Collection<B> beans) {
            StatementSupport.this.update(beans);
        }

        @Override
        public void delete(Collection<B> beans) {
            StatementSupport.this.delete(beans);
        }
    }

    private Methods<Object> methods = new Methods<Object>();

    @SuppressWarnings("unchecked")
    private <B> Methods<B> methods() {
        return (Methods<B>) methods;
    }

    public <B> void save(Collection<B> beans, ItemHandler<B> handler) {
        CollectionPersistUtil.save(beans, handler, this.<B>methods());
    }

    public <B> void save(Collection<B> beans) {
        @SuppressWarnings("unchecked")
        BeanHandler<B> handler = new BeanHandler<B>().init(beans);

        if (handler != null) {
            save(beans, handler);
        }
    }

    public <B> void persist(Collection<B> newState, Collection<B> oldState, ItemHandler<B> handler) {
        CollectionPersistUtil.persist(newState, oldState, handler, this.<B>methods());
    }

    public <B> void persist(Collection<B> newState, Collection<B> oldState) {
        @SuppressWarnings("unchecked")
        BeanHandler<B> handler = new BeanHandler<B>().init(newState, oldState);

        if (handler != null) {
            persist(newState, oldState, handler);
        }
    }

    /**
     * Inserts or updates beans by primary key mapping
     * 
     * @param beans
     *            Beans to save
     */
    public <B> void save(B... beans) {
        if (ArrayUtils.isEmpty(beans)) {
            return;
        }
        save(Arrays.asList(beans));
    }

    public <T> QueryStatement<T> queryStm(ListQuery<T> listQuery) {
        return new QueryStatement<T>(listQuery, getStatementBuilder(), getJdbcTemplate());
    }

    public <T, R> void loadRelations(Collection<T> targets, RelationMapper<T, R> relationMapper) {
        RelationUtil.loadRelations(targets, relationMapper, getRelationLoader(relationMapper));
    }

    private <R> RelationLoader<R> getRelationLoader(final RelationMapper<?, R> relationMapper) {
        return new RelationLoader<R>() {
            @Override
            public List<R> loadRelations(Collection<Object> targetIds) {
                WherePart where = Where.eq(relationMapper.getRelationProperty(), targetIds);
                if (relationMapper.getWhere() != null) {
                    where = where.and(relationMapper.getWhere());
                }
                return loadStm(relationMapper.getRelationClass()).where(where).all();
            }
        };
    }

    public <T> void loadRelations(Collection<T> targets, RelationMapper<T, ?>... relationMappers) {
        for (RelationMapper<T, ?> mapper : relationMappers) {
            loadRelations(targets, mapper);
        }
    }

    @SuppressWarnings("unchecked")
    public <T> void loadRelations(T target, RelationMapper<T, ?>... relationMappers) {
        loadRelations(Arrays.asList(target), relationMappers);
    }
}