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

org.fingertip.simpledao.template.SimpleDao Maven / Gradle / Ivy

The newest version!
package org.fingertip.simpledao.template;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

import javax.sql.DataSource;

import org.fingertip.simpledao.bean.*;
import org.fingertip.simpledao.common.DaoConfig;
import org.fingertip.simpledao.enums.ExecuteType;
import org.fingertip.simpledao.exception.DaoException;
import org.fingertip.simpledao.query.Query;
import org.fingertip.simpledao.utils.ModelUtil;
import org.fingertip.simpledao.utils.SqlBuilder;

public class SimpleDao extends AbstractDaoTemplate{
	
	public SimpleDao() {}
	
	public SimpleDao(DataSource dataSource) {
		super(dataSource);
	}
	
	public SimpleDao(DaoConfig config) {
		super(config);
	}

	/**
	 * 保存实体
	 * @param entity 实体对象 对应数据库表的实体
	 * @param entityClass 实体对应的class对象
	 * @param  实体泛型
	 * @return 返回对应实体
	 * @throws SQLException
	 */
	@Override
	public  boolean save(Object entity, Class entityClass) throws SQLException {
		List entities = new ArrayList<>();
		entities.add(entity);
		return batchSave(entities , entityClass);
	}

	/**
	 * 批量保存实体
	 * @param entities 实体集合
	 * @param entityClass 实体的class对象
	 * @param  实体泛型
	 * @return 返回实体
	 * @throws SQLException
	 */
	@Override
	public  boolean batchSave(List entities, Class entityClass) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(entityClass,ExecuteType.EXECUTE_TYPE_INSERT);
		String sql = SqlBuilder.buildInsertSql(message.getTableName(),message.getEntityDbFieldNames().values(),entities.size());
		Object[] args = ModelUtil.entityToArgs(entities, message.getDbEntityFieldNames().values(), entityClass);
		ExecuteResult result = executeUpdate(sql, args);
		if(result.getUpdateCounts()[0] != entities.size()){
			return false;
		}
		Field idField = message.getDbFields().get(message.getIdName());
		if(idField != null){			
			idField.setAccessible(true);
			for(int i = 0;i < entities.size();i++){
				Object entity = entities.get(i);
				try {
					idField.set(entity, result.getGeneratedKeys().get(i));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return true;
	}

	/**
	 * 更新实体
	 * @param entity 实体对象
	 * @param entityClass 实体的class对象
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  boolean update(Object entity, Class entityClass) throws SQLException {
		List entities = new ArrayList<>();
		entities.add(entity);
		return this.batchUpdate(entities, entityClass);
	}

	/**
	 * 批量更新实体
	 * @param entities 实体集合
	 * @param entityClass 实体的class对象
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  boolean batchUpdate(List entities, Class entityClass) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(entityClass,ExecuteType.EXECUTE_TYPE_UPDATE);
		Map fieldNameMap = message.getEntityDbFieldNames();
		String idName = message.getIdName();
		if(idName == null){
			throw new DaoException("未定义主键字段(更新记录是主键作为条件的)");
		}
		String sql = SqlBuilder.buildUpdateSql(message.getTableName(), message.getEntityDbFieldNames().values(), idName);
		Collection fieldNames = fieldNameMap.keySet();
		List argsList = new ArrayList<>();
    	for(Object entity : entities){
    		if(entity == null){
    			throw new NullPointerException("保存的数据中带有null值的实体类");
    		}
    		Object idVal = ModelUtil.getIdVal(entity,entityClass,message,idName);
			if(idVal == null || String.valueOf(idVal).equals("") || String.valueOf(idVal).equals("0")){
				throw new DaoException("主键 "+idName+"为"+idVal);
			}
    		List args = new ArrayList<>();
    		for(String name : fieldNames){
    			ModelUtil.entityToArgs(args, entity, name, entityClass);
    		}
				
			args.add(idVal);
    		argsList.add(args.toArray());
    	}
		executeBatchUpdate(sql, argsList);
		return true;
	}

	/**
	 * 保存或更新实体
	 *	如果有主键值则更新,没主键则插入
	 * @param entity
	 * @param entityClass
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  boolean saveOrUpdate(Object entity, Class entityClass) throws SQLException {
		List entities = new ArrayList<>();
		entities.add(entity);
		return batchSaveOrUpdate(entities, entityClass);
	}

	/**
	 * 批量保存或更新实体
	 * 	如果有主键值则更新,没主键则插入
	 * @param entities
	 * @param entityClass
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  boolean batchSaveOrUpdate(List entities, Class entityClass) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(entityClass,ExecuteType.EXECUTE_TYPE_UPDATE);
		String idName = message.getIdName();
		if(idName == null){
			throw new DaoException("未定义主键字段(更新记录是主键作为条件的)");
		}
		
		Map entityMap = new HashMap<>();
		List updateEntities = new ArrayList<>();
		List saveEntities = new ArrayList<>();
		List idValues = new ArrayList<>();
    	for(Object entity : entities){
    		if(entity == null){
    			throw new NullPointerException("实体类为空");
    		}
			Object idVal = ModelUtil.getIdVal(entity,entityClass,message,idName);
    		boolean isUpdate = true;
    		if(idVal == null || String.valueOf(idVal).equals("") || String.valueOf(idVal).equals("0")){
    			isUpdate = false;
    		}else{
    			idValues.add(idVal);
    		}
			if(isUpdate){
				entityMap.put(String.valueOf(idVal), entity);
			}else{
				saveEntities.add(entity);
			}
    	}
    	if(!idValues.isEmpty()){
    		Query query = new Query(entityClass);
			query.fields(idName);
    		query.in(idName, idValues);
    		Field idField = message.getDbFields().get(idName);
    		List list = this.findColumn(query, idField.getType());
    		if(list.isEmpty()){
    			saveEntities.addAll(entityMap.values());
    		}else{
    			for(Object object : list){
    				String key = String.valueOf(object);
    				if(entityMap.containsKey(key)){
    					updateEntities.add(entityMap.get(key));
    				}else {
    					idField.setAccessible(true);
    					Object entity2 = entityMap.get(key);
    					try {
    						Object inst = entityClass.newInstance();
    						Object nullIdVal = idField.get(inst);
    						idField.set(entity2, nullIdVal);
    						saveEntities.add(entity2);
    					} catch (Exception e) {
    						e.printStackTrace();
//    						throw new DaoException("不存在的记录钟的主键值需要删除后作为新纪录插入,但删除异常");
    					}
    				}
    			}
    		}
    	}
    	SimpleDao tx = null;
    	if(this.isTransactionOpen()){
    		tx = this;
    	}else{
    		tx = this.openTransaction();
    	}
    	if(!saveEntities.isEmpty()){
    		boolean batchSave = tx.batchSave(saveEntities, entityClass);
    		if(!batchSave){
    			tx.getTxConnection().rollback();
    			return false;
    		}
    	}
    	if(!updateEntities.isEmpty()){
    		boolean batchUpdate = tx.batchUpdate(updateEntities, entityClass);
    		if(!batchUpdate){
    			tx.getTxConnection().rollback();
    			return false;
    		}
    	}
    	if(!this.isTransactionOpen() && tx.isTransactionOpen()){
    		tx.submitTransaction();
    	}
		return true;
	}

	/**
	 * 删除实体
	 * @param entity
	 * @param entityClass
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  boolean delete(Object entity, Class entityClass) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(entityClass,ExecuteType.EXECUTE_TYPE_DELETE);
		String idName = message.getIdName();
		if(idName == null){
			throw new DaoException("未定义主键字段(更新记录是主键作为条件的)");
		}
		String sql = SqlBuilder.buildDeleteSql(message.getTableName(), idName);
		if(entity == null){
			throw new NullPointerException("保存的实体为null");
		}
		Object idVal = ModelUtil.getIdVal(entity,entityClass,message,idName);

		if(idVal == null || String.valueOf(idVal).equals("") || String.valueOf(idVal).equals("0")){
			throw new DaoException("主键 " + idName + "为" + idVal + "。");
		}
		executeUpdate(sql, idVal);
		return true;
	}

	/**
	 * 根据id查询实体
	 * @param id
	 * @param entityClass 指定对应表的实体,需要用该实体获取表名和返回数据
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  T findById(Object id, Class entityClass) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(entityClass,ExecuteType.EXECUTE_TYPE_SELECT_ENTITY);
		String idName = message.getIdName();
		String sql = "select * from " +
				message.getTableName() +
				" where " +
				idName +
				" = ? ";
		List list = executeQueryAsEntity(sql, entityClass,message, id);
		if(!list.isEmpty()){
			return list.get(0);
		}
		return null;
	}

	/**
	 * 查询全部
	 * @param entityClass 指定对应表的实体,需要用该实体获取表名和返回数据
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  List findAll(Class entityClass) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(entityClass,ExecuteType.EXECUTE_TYPE_UPDATE);
		String sql = "select * from " + message.getTableName();
		return executeQueryAsEntity(sql, entityClass,message);
	}

	/**
	 * 统计
	 * @param entityClass 指定对应表的实体,需要用该实体获取表名
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  long count(Class entityClass) throws SQLException {
		String tableName = ModelUtil.getTableName(entityClass);
		String sql = "select count(*) from " + tableName;
		List res = executeQueryAsList(sql);
		return (long)res.get(0)[0];
	}

	/**
	 * 插入记录
	 * @param sql
	 * @param args
	 * @return
	 * @throws SQLException
	 */
	@Override
	public List insert(String sql, Object... args) throws SQLException {
		List argsList = new ArrayList<>();
		argsList.add(args);
		return batchInsert(sql, argsList);
	}

	/**
	 * 批量插入
	 * @param sql
	 * @param args
	 * @return
	 * @throws SQLException
	 */
	@Override
	public List batchInsert(String sql, List args) throws SQLException {
		ExecuteResult result = executeBatchUpdate(sql, args);
		return result.getGeneratedKeys();
	}

	/**
	 * 更新记录
	 * @param sql
	 * @param args
	 * @return
	 * @throws SQLException
	 */
	@Override
	public int[] update(String sql, Object... args) throws SQLException {
		List argsList = new ArrayList<>();
        SqlFormatResult result = SqlBuilder.formatSql(sql, args);
        argsList.add(result.getArgs());
		return batchUpdate(result.getSql(), argsList);
	}

	/**
	 * 批量更新
     *  批量更新暂不支持指定下标的?号传参
	 * @param sql
	 * @param args
	 * @return
	 * @throws SQLException
	 */
	@Override
	public int[] batchUpdate(String sql, List args) throws SQLException {
		ExecuteResult result = executeBatchUpdate(sql, args);
		return result.getUpdateCounts();
	}

	/**
	 * List查询
	 * @param sql 查询语句
	 * @param args 查询参数
	 * @return 返回一个Object数组的列表,一个Object数组表示一行记录,没有键,按查询字段顺序储存
	 * @throws SQLException
	 */
	@Override
	public List findAsList(String sql, Object... args) throws SQLException {
        SqlFormatResult result = SqlBuilder.formatSql(sql, args);
        return executeQueryAsList(result.getSql(), result.getArgs());
	}

	/**
	 * Map查询
	 * @param sql
	 * @param args
	 * @return 返回一个map列表 一个map表示一行记录,map的key为字段名,value为字段值
	 * @throws SQLException
	 */
	@Override
	public List> findAsMap(String sql, Object... args) throws SQLException {
        SqlFormatResult result = SqlBuilder.formatSql(sql, args);
        return executeQueryAsMap(result.getSql(), result.getArgs());
	}

	/**
	 * 结果实体查询
	 * 	查询时将会自动将数据映射到指定的结果实体中
	 * @param sql 指定查询的sql
	 * @param resultEntity 指定返回结果的映射实体
	 * @param args
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  List find(String sql, Class resultEntity, Object... args) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(resultEntity, ExecuteType.EXECUTE_TYPE_SELECT_SQL);
        SqlFormatResult result = SqlBuilder.formatSql(sql, args);
        return executeQueryAsEntity(result.getSql(), resultEntity, message, result.getArgs());
	}

	/**
	 * 查询一行
	 * 	如果有多行记录也只返回第一行
	 * @param sql
	 * @param resultEntity 指定返回的结果实体
	 * @param args
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  T findOne(String sql, Class resultEntity, Object... args) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(resultEntity, ExecuteType.EXECUTE_TYPE_SELECT_SQL);
		SqlFormatResult result = SqlBuilder.formatSql(sql, args);
		List entities = executeQueryAsEntity(result.getSql(), resultEntity, message, result.getArgs());
		if(!entities.isEmpty()){
			return entities.get(0);
		}
		return null;
	}

	/**
	 * map查询一行
	 * @param sql
	 * @param args
	 * @return 返回一个map,map表示一行记录,map的key为字段名,value为字段值
	 * @throws SQLException
	 */
	@Override
	public Map findOneAsMap(String sql, Object... args) throws SQLException {
		SqlFormatResult result = SqlBuilder.formatSql(sql, args);
		List> maps = executeQueryAsMap(result.getSql(), result.getArgs());
		if(!maps.isEmpty()){
			return maps.get(0);
		}
		return null;
	}

	/**
	 * 查询单值
	 * 	如:select name from user;又如:select count(*) from user;
	 * 	适合一个值的查询,或统计查询
	 * @param sql
	 * @param valueClass
	 * @param args
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@SuppressWarnings("unchecked")
	@Override
	public  T findOneValue(String sql, Class valueClass, Object... args) throws SQLException {
        SqlFormatResult result = SqlBuilder.formatSql(sql, args);
        List list = executeQueryAsList(result.getSql(), result.getArgs());
		if(!list.isEmpty()){
			Object[] objects = list.get(0);
			if(objects.length > 0){
				return (T)objects[0];
			}
		}
		return null;
	}

	/**
	 * 查询一列
	 * @param sql
	 * @param valueClass
	 * @param args
	 * @param 
	 * @return 返回该列的数组
	 * @throws SQLException
	 */
	@SuppressWarnings("unchecked")
	@Override
	public  List findColumn(String sql, Class valueClass, Object... args) throws SQLException {
        SqlFormatResult formatResult = SqlBuilder.formatSql(sql, args);
        List list = executeQueryAsList(formatResult.getSql(), formatResult.getArgs());
		List result = new ArrayList<>();
		if(!list.isEmpty()){
			for(Object[] objects : list){
				if(objects.length > 0){
					result.add((T)objects[0]);
				}
			}
		}
		return result;
	}

	/**
	 * 统计
	 * @param tableName 指定统计的表名
	 * @return
	 * @throws SQLException
	 */
	@Override
	public long count(String tableName) throws SQLException {
		List list = executeQueryAsList("select count(*) from " + tableName);
		if(!list.isEmpty()){
			Object[] objects = list.get(0);
			if(objects.length > 0){
				return (long)objects[0];
			}
		}
		return 0;
	}

	/**
	 * 分页查询
	 * @param sql 查询语句,只需要指定正常查询语句,不需要limit和统计语句,该方法会自动封装
	 * @param resultEntity 返回的结果实体
	 * @param pageRequest 分页信息,通过该对象指定查询第几页,一页几条记录
	 * @param args
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  PageResult page(String sql, Class resultEntity, PageRequest pageRequest, Object... args)
			throws  SQLException {
        SqlFormatResult result = SqlBuilder.formatSql(sql, args);
        sql = result.getSql();
        args = result.getArgs();
        List argList = new ArrayList<>();
		if(args != null && args.length != 0){
			argList.addAll(Arrays.asList(args));
		}
		long count = 0;
		List rs = executeQueryAsList("select count(1) from (" + sql + ") as data ", result.getArgs());
		if(!rs.isEmpty()){
			Object[] objects = rs.get(0);
			if(objects.length > 0){
				count = (long)objects[0];
			}
		}
		sql += " limit ?,?";
		argList.add((pageRequest.getPageIndex() - 1) * pageRequest.getPageSize());
		argList.add(pageRequest.getPageSize());
        ModelClassMessage message = ModelUtil.getModelClassMessage(resultEntity, ExecuteType.EXECUTE_TYPE_SELECT_SQL);
        List list = executeQueryAsEntity(sql, resultEntity, message, argList.toArray());
        return new PageResult<>(list, count, pageRequest.getPageSize(), pageRequest.getPageIndex());
	}

	/**
	 * 查询
	 * @param query 指定查询的query
	 * @param resultEntity
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  List find(Query query,Class resultEntity) throws SQLException {
		ModelClassMessage message = ModelUtil.getModelClassMessage(resultEntity, ExecuteType.EXECUTE_TYPE_SELECT_ENTITY);
		return executeQueryAsEntity(query.buildSql(resultEntity),resultEntity,message, query.getArgs().toArray());
	}

	/**
	 * 查询单值
	 * 	该方法返回结果实体,返回的值会映射到实体中对应的字段上
	 * @param query
	 * @param valueEntity
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  T findOneValue(Query query, Class valueEntity) throws SQLException {
		if(query.getFields().isEmpty()){
			throw new DaoException("findOneValue方法必须指定字段");
		}
		return findOneValue(query.buildSql(null),valueEntity,query.getArgs());
	}

	/**
	 * 查询一列(Query方式)
	 * @param query
	 * @param columnType
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@SuppressWarnings("unchecked")
	@Override
	public  List findColumn(Query query, Class columnType)
			throws  SQLException {
		query.setFields(new ArrayList<>());
		List list = executeQueryAsList(query.buildSql(), query.getArgs().toArray());
		List rs = new ArrayList<>();
		for(Object[] array : list){
			rs.add((T)array[0]);
		}
		return rs;
	}

	/**
	 * 查询一个实体
	 * @param query
	 * @param resultEntity
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  T findOne(Query query,Class resultEntity) throws SQLException {
		List list = find(query, resultEntity);
		if(!list.isEmpty()){
			return list.get(0);
		}
		return null;
	}

	/**
	 * 分页查询(Query方式)
	 * @param query
	 * @param resultEntity
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  PageResult page(Query query,Class resultEntity) throws SQLException {
		return page(query, resultEntity, 1, 10);
	}

	/**
	 * 分页查询(Query方式)
	 * @param query
	 * @param resultEntity
	 * @param pageIndex
	 * @param pageSize
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  PageResult page(Query query, Class resultEntity, int pageIndex, int pageSize)
			throws  SQLException {
		String sql = query.buildSql();
		List args = query.getArgs();
		Long count = findOneValue("select count(1) from (" + sql + ") as data ", long.class, args.toArray());
//		args.add((pageIndex - 1) * pageSize);
//		args.add(pageSize);
		query.limit((pageIndex - 1) * pageSize, pageSize);
		List list = find(query, resultEntity);
		
		return new PageResult<>(list, count, pageSize, pageIndex);
	}

	/**
	 * 分页查询(Query方式)
	 * @param query
	 * @param entityClass
	 * @param pageRequest
	 * @param 
	 * @return
	 * @throws SQLException
	 */
	@Override
	public  PageResult page(Query query, Class entityClass, PageRequest pageRequest)
			throws  SQLException {
		return page(query, entityClass, pageRequest.getPageIndex(), pageRequest.getPageSize());
	}

	/**
	 * 开启事务
	 * @return
	 * @throws SQLException
	 */
	@Override
	public SimpleDao openTransaction() throws SQLException {
		SimpleDao daoTemplate = new SimpleDao();
		DataSource ds = this.getDataSource();
		daoTemplate.setDataSource(ds);
		Connection conn = ds.getConnection();
		conn.setAutoCommit(false);
		daoTemplate.setTxConnection(conn);
		daoTemplate.setTransactionOpen(true);
		return daoTemplate;
	}

	/**
	 * 提交事务
	 * @throws SQLException
	 */
	@Override
	public void submitTransaction() throws SQLException {
		this.getTxConnection().commit();
		this.closeTransaction();
	}

	/**
	 * 事务回滚
	 * @throws SQLException
	 */
	@Override
	public void rollback() throws SQLException {
		this.getTxConnection().rollback();
		this.closeTransaction();		
	}
	
}