/* * Copyright 2010 Research Studios Austria Forschungsgesellschaft mBH * * This file is part of easyrec. * * easyrec is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * easyrec 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with easyrec. If not, see <http://www.gnu.org/licenses/>. */ package org.easyrec.store.dao.core.impl; import org.easyrec.model.core.RecommendationVO; import org.easyrec.model.core.RecommendedItemVO; import org.easyrec.model.core.transfer.TimeConstraintVO; import org.easyrec.store.dao.core.RecommendationDAO; import org.easyrec.store.dao.core.RecommendedItemDAO; import org.easyrec.store.dao.impl.AbstractBaseRecommendationDAOMysqlImpl; import org.easyrec.utils.spring.store.ResultSetIteratorMysql; import org.easyrec.utils.spring.store.dao.DaoUtils; import org.easyrec.utils.spring.store.dao.annotation.DAO; import org.easyrec.utils.spring.store.service.sqlscript.SqlScriptService; import org.springframework.jdbc.core.PreparedStatementCreatorFactory; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Iterator; /** * This class provides a Mysql implementation of the {@link org.easyrec.store.dao.core.RecommendationDAO} interface. * <p/> * <p><b>Company: </b> * SAT, Research Studios Austria</p> * <p/> * <p><b>Copyright: </b> * (c) 2007</p> * <p/> * <p><b>last modified:</b><br/> * $Author: dmann $<br/> * $Date: 2011-12-20 15:22:22 +0100 (Di, 20 Dez 2011) $<br/> * $Revision: 18685 $</p> * * @author Roman Cerny */ @DAO public class RecommendationDAOMysqlImpl extends AbstractBaseRecommendationDAOMysqlImpl<RecommendationVO<Integer, Integer>> implements RecommendationDAO { // members private RecommendationVORowMapper recommendationVORowMapper = new RecommendationVORowMapper(); private RecommendedItemDAO recommendedItemDAO; // constructor public RecommendationDAOMysqlImpl(DataSource dataSource, RecommendedItemDAO recommendedItemDAO, SqlScriptService sqlScriptService) { super(sqlScriptService); setDataSource(dataSource); this.recommendedItemDAO = recommendedItemDAO; // output connection information if (logger.isInfoEnabled()) { try { logger.info(DaoUtils.getDatabaseURLAndUserName(dataSource)); } catch (Exception e) { logger.error(e); } } } // abstract (generic) method implementation of 'AbstractBaseRecommendationDAOMysqlImpl<RecommendationVO>' @Override public int insertRecommendation( RecommendationVO<Integer, Integer> recommendation) { if (logger.isTraceEnabled()) { logger.trace("inserting recommendation=" + recommendation); } // validate unique key validateUniqueKey(recommendation); StringBuilder query = new StringBuilder("INSERT INTO "); query.append(DEFAULT_TABLE_NAME); query.append(" SET "); query.append(DEFAULT_TENANT_COLUMN_NAME); query.append("=?, "); query.append(DEFAULT_USER_COLUMN_NAME); query.append("=?, "); query.append(DEFAULT_QUERIED_ITEM_COLUMN_NAME); query.append("=?, "); query.append(DEFAULT_QUERIED_ITEM_TYPE_COLUMN_NAME); query.append("=?, "); query.append(DEFAULT_QUERIED_ASSOC_TYPE_COLUMN_NAME); query.append("=?, "); query.append(DEFAULT_RELATED_ACTION_TYPE_COLUMN_NAME); query.append("=?, "); query.append(DEFAULT_RECOMMENDATION_STRATEGY_COLUMN_NAME); query.append("=?, "); query.append(DEFAULT_EXPLANATION_COLUMN_NAME); query.append("=?, "); query.append(DEFAULT_RECOMMENDATION_TIME_COLUMN_NAME); query.append("=NOW()"); Object[] args = {recommendation.getTenant(), recommendation.getUser(), recommendation.getQueriedItem(), recommendation.getQueriedItemType(), recommendation.getQueriedAssocType(), recommendation.getRelatedActionType(), recommendation.getRecommendationStrategy(), recommendation.getExplanation()}; int[] argTypes = {Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR}; PreparedStatementCreatorFactory factory = new PreparedStatementCreatorFactory(query.toString(), argTypes); factory.setReturnGeneratedKeys(true); KeyHolder keyHolder = new GeneratedKeyHolder(); int rowsAffected = getJdbcTemplate().update(factory.newPreparedStatementCreator(args), keyHolder); // retrieve auto increment id, and set to VO recommendation.setId(keyHolder.getKey().intValue()); // inserting all RecommendedItemVOs (if recommended items exist) if (recommendation.getRecommendedItems() != null && recommendation.getRecommendedItems().size() > 0) { for (RecommendedItemVO<Integer, Integer> recommendedItem : recommendation.getRecommendedItems()) { // store auto increment id to all RecommendedItemVOs recommendedItem.setRecommendationId(recommendation.getId()); recommendedItemDAO.insertRecommendedItem(recommendedItem); } } return rowsAffected; } @Override public RecommendationVO<Integer, Integer> loadRecommendation( Integer recommendationId) { // validate input if (recommendationId == null) { throw new IllegalArgumentException("missing 'recommendationId'"); } if (logger.isTraceEnabled()) { logger.trace("retrieving recommendation with id=" + recommendationId); } Object[] args = {recommendationId}; int[] argTypes = {Types.INTEGER}; return getJdbcTemplate() .queryForObject(getRecommendationQueryString(), args, argTypes, recommendationVORowMapper); } @Override public Iterator<RecommendationVO<Integer, Integer>> getRecommendationIterator( int bulkSize) { return new ResultSetIteratorMysql<RecommendationVO<Integer, Integer>>( getDataSource(), bulkSize, getRecommendationIteratorQueryString(), recommendationVORowMapper); } @Override public Iterator<RecommendationVO<Integer, Integer>> getRecommendationIterator( int bulkSize, TimeConstraintVO timeConstraints) { if (timeConstraints == null || timeConstraints.getDateFrom() == null && timeConstraints.getDateTo() == null) { return getRecommendationIterator(bulkSize); } Object[] args = new Object[1]; int[] argTypes = {Types.TIMESTAMP}; DaoUtils.ArgsAndTypesHolder holder = new DaoUtils.ArgsAndTypesHolder(args, argTypes); String s = getRecommendationIteratorQueryString(timeConstraints, holder); return new ResultSetIteratorMysql<RecommendationVO<Integer, Integer>>( getDataSource(), bulkSize, s, holder.getArgs(), holder.getArgTypes(), recommendationVORowMapper); } ////////////////////////////////////////////////////////////////////////////// // private methods private void validateUniqueKey( RecommendationVO<Integer, Integer> recommendation) { // NOTE: leave out check for 'recommendationTime' since it is automatically generated on database level // do not check for recommended items either, since each recommendation should be stored for future evaluations, // store recommendations even if no items could be recommended. if (recommendation.getTenant() == null) { throw new IllegalArgumentException( "missing constraints, unique key (tenantId, recommendationTime) must be set, missing 'itemId'"); } } ////////////////////////////////////////////////////////////////////////////// // public inner classes public class RecommendationVORowMapper implements RowMapper<RecommendationVO<Integer, Integer>> { public RecommendationVO<Integer, Integer> mapRow(ResultSet rs, int rowNum) throws SQLException { RecommendationVO<Integer, Integer> recommendation = new RecommendationVO<Integer, Integer>( DaoUtils.getInteger(rs, DEFAULT_ID_COLUMN_NAME), DaoUtils.getInteger(rs, DEFAULT_TENANT_COLUMN_NAME), DaoUtils.getInteger(rs, DEFAULT_USER_COLUMN_NAME), DaoUtils.getInteger(rs, DEFAULT_QUERIED_ITEM_COLUMN_NAME), DaoUtils.getInteger(rs, DEFAULT_QUERIED_ITEM_TYPE_COLUMN_NAME), DaoUtils.getInteger(rs, DEFAULT_QUERIED_ASSOC_TYPE_COLUMN_NAME), DaoUtils.getInteger(rs, DEFAULT_RELATED_ACTION_TYPE_COLUMN_NAME), DaoUtils.getStringIfPresent(rs, DEFAULT_RECOMMENDATION_STRATEGY_COLUMN_NAME), DaoUtils.getStringIfPresent(rs, DEFAULT_EXPLANATION_COLUMN_NAME), DaoUtils.getDate(rs, DEFAULT_RECOMMENDATION_TIME_COLUMN_NAME), recommendedItemDAO .getRecommendedItemsOfRecommendation(DaoUtils.getInteger(rs, DEFAULT_ID_COLUMN_NAME))); return recommendation; } } }