Java tutorial
/* * Copyright 2009-2010 the original author or authors. * * 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 i 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.sinosoft.one.data.jade.statement; import com.sinosoft.one.data.jade.annotation.SQLType; import com.sinosoft.one.data.jade.dataaccess.DataAccess; import com.sinosoft.one.data.jade.dataaccess.DataAccessImpl; import com.sinosoft.one.data.jade.statement.Querier; import com.sinosoft.one.data.jade.statement.StatementMetaData; import com.sinosoft.one.data.jade.statement.StatementRuntime; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.slf4j.Logger; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.jdbc.core.RowMapper; import javax.persistence.EntityManager; import java.lang.reflect.Array; import java.util.*; /** * SELECT * * @author [qieqie.wang@gmail.com] * @author [in355hz@gmail.com] */ public class SelectQuerier implements Querier { private final RowMapper<?> rowMapper; private final Class<?> returnType; private final EntityManager em; private Log log = LogFactory.getLog(SelectQuerier.class); public SelectQuerier(EntityManager em, StatementMetaData metaData, RowMapper<?> rowMapper) { this.em = em; this.returnType = metaData.getMethod().getReturnType(); this.rowMapper = rowMapper; } public Object execute(SQLType sqlType, StatementRuntime... runtimes) { return execute(sqlType, (StatementRuntime) runtimes[0]); } public Object execute(SQLType sqlType, StatementRuntime runtime) { String sql = runtime.getSQL(); Object[] args = runtime.getArgs(); DataAccess dataAccess = new DataAccessImpl(em); List<?> listResult = null; Pageable pageable = null; Sort sort = null; boolean isPage = false; boolean isSort = false; Map<String, Object> paramMap = runtime.getParameters(); for (String key : paramMap.keySet()) { if (paramMap.get(key) instanceof Pageable) { pageable = (Pageable) paramMap.get(key); isPage = true; } else if (paramMap.get(key) instanceof Sort) { sort = (Sort) paramMap.get(key); isSort = true; } } if (isPage && !isSort) { if (returnType == Page.class) { String countSql = parseCountSql(sql); Page<?> page = dataAccess.selectByPage(pageable, sql, countSql, args, rowMapper); return page; } else { try { log.error("The return type[" + returnType + "] must be " + Page.class); throw new Exception("The return type [\"+returnType+\"] is invalid"); } catch (Exception e) { e.printStackTrace(); } } } else if (!isPage && isSort) { return dataAccess.selectBySort(sort, sql, args, rowMapper); } else if (isPage && isSort) { try { log.error("Can not use Params:[" + Pageable.class + " and " + Sort.class + "at the same time."); throw new Exception( "Can not use Params:[" + Pageable.class + " and " + Sort.class + "at the same time."); } catch (Exception e) { e.printStackTrace(); } } else { listResult = dataAccess.select(sql, args, rowMapper); final int sizeResult = listResult.size(); // Result ? if (returnType.isAssignableFrom(List.class)) { // List ? return listResult; } else if (returnType.isArray() && byte[].class != returnType) { Object array = Array.newInstance(returnType.getComponentType(), sizeResult); if (returnType.getComponentType().isPrimitive()) { int len = listResult.size(); for (int i = 0; i < len; i++) { Array.set(array, i, listResult.get(i)); } } else { listResult.toArray((Object[]) array); } return array; } else if (Map.class.isAssignableFrom(returnType)) { // KeyValuePair ?? Map // entry.key?nullHashMap Map<Object, Object> map; if (returnType.isAssignableFrom(HashMap.class)) { map = new HashMap<Object, Object>(listResult.size() * 2); } else if (returnType.isAssignableFrom(Hashtable.class)) { map = new Hashtable<Object, Object>(listResult.size() * 2); } else { throw new Error(returnType.toString()); } for (Object obj : listResult) { if (obj == null) { continue; } Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj; if (map.getClass() == Hashtable.class && entry.getKey() == null) { continue; } map.put(entry.getKey(), entry.getValue()); } return map; } else if (returnType.isAssignableFrom(HashSet.class)) { // Set ? return new HashSet<Object>(listResult); } else { if (sizeResult == 1) { // ? Bean?Boolean return listResult.get(0); } else if (sizeResult == 0) { // null if (returnType.isPrimitive()) { String msg = "Incorrect result size: expected 1, actual " + sizeResult + ": " + runtime.getMetaData(); throw new EmptyResultDataAccessException(msg, 1); } else { return null; } } else { // IncorrectResultSizeDataAccessException String msg = "Incorrect result size: expected 0 or 1, actual " + sizeResult + ": " + runtime.getMetaData(); throw new IncorrectResultSizeDataAccessException(msg, 1, sizeResult); } } } return listResult; } private String parseCountSql(String sql) { // sql = StringUtils.lowerCase(sql); int end = StringUtils.indexOf(sql.toLowerCase(), "from"); String s = StringUtils.substring(sql, end); return "select count(1) " + s; } }