DataBaseDaoAbstract

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;

public abstract class DataBaseDaoAbstract<T> {
    
    private static Logger logger = CocoLoggerFactory.getLogger(DataBaseDaoAbstract.class);
    
    protected T execQueryObject(String sql, Object ...params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            if(result.next()) {
                T t = this.parse(result);
                return t;
            }
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
        return null;
    }
    
    protected T execQueryObject(String sql, Collection<Object> params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            if(result.next()) {
                T t = this.parse(result);
                return t;
            }
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
        return null;
    }
    
    protected <K> K execQueryObject(String sql, Class<K> clazz, Object ...params) throws Exception {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            if(result.next()) {
                if(this.isSimpleClass(clazz)) {
                    return (K) this.getValue(result, clazz, 1);
                }
                K instance = clazz.newInstance();
                Map<Integer, Method> columnMethodMap = this.generateMethodMap(clazz, result.getMetaData());
                for(Entry<Integer, Method> entry : columnMethodMap.entrySet()) {
                    Object param = this.getValue(result, entry.getValue().getParameterTypes()[0], entry.getKey());
                    entry.getValue().invoke(instance, param);
                }
                return instance;
            }
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
        return null;
    }
    protected <K> K execQueryObject(String sql, Class<K> clazz, Collection<Object> params) throws Exception {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            if(result.next()) {
                if(this.isSimpleClass(clazz)) {
                    return (K) this.getValue(result, clazz, 1);
                }
                K instance = clazz.newInstance();
                Map<Integer, Method> columnMethodMap = this.generateMethodMap(clazz, result.getMetaData());
                for(Entry<Integer, Method> entry : columnMethodMap.entrySet()) {
                    Object param = this.getValue(result, entry.getValue().getParameterTypes()[0], entry.getKey());
                    entry.getValue().invoke(instance, param);
                }
                return instance;
            }
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
        return null;
    }
    
    protected <K> List<K> execQueryObjects(String sql, Class<K> clazz, Object ...params) throws Exception {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        List<K> returnList = Lists.newArrayList();
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            if(this.isSimpleClass(clazz)) {
                while(result.next()) {
                    returnList.add((K) this.getValue(result, clazz, 1));
                }
            }
             Map<Integer, Method> columnMethodMap = this.generateMethodMap(clazz, result.getMetaData());
            while(result.next()) {
                K instance = clazz.newInstance();
                for(Entry<Integer, Method> entry : columnMethodMap.entrySet()) {
                    Object param = this.getValue(result, entry.getValue().getParameterTypes()[0], entry.getKey());
                    entry.getValue().invoke(instance, param);
                }
                returnList.add(instance);
            }
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
        return returnList;
    }
    
    protected <K> List<K> execQueryObjects(String sql, Class<K> clazz, Collection<Object> params) throws Exception {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        List<K> returnList = Lists.newArrayList();
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            if(this.isSimpleClass(clazz)) {
                while(result.next()) {
                    returnList.add((K) this.getValue(result, clazz, 1));
                }
            }
             Map<Integer, Method> columnMethodMap = this.generateMethodMap(clazz, result.getMetaData());
            while(result.next()) {
                K instance = clazz.newInstance();
                for(Entry<Integer, Method> entry : columnMethodMap.entrySet()) {
                    Object param = this.getValue(result, entry.getValue().getParameterTypes()[0], entry.getKey());
                    entry.getValue().invoke(instance, param);
                }
                returnList.add(instance);
            }
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
        return returnList;
    }
    
    private boolean isSimpleClass(Class<?> clazz) {
        if(clazz.isPrimitive()) {
            return true;
        }
        if(clazz.equals(Integer.class) || clazz.equals(Long.class) 
                || clazz.equals(Short.class) || clazz.equals(String.class)
                || clazz.equals(Float.class) || clazz.equals(Double.class)
                || clazz.equals(BigDecimal.class) || clazz.equals(Byte.class)
                || clazz.equals(Boolean.class) || Date.class.isAssignableFrom(clazz)) {
            return true;
        }
        return false;
        
    }
    
    private Map<Integer, Method> generateMethodMap(Class<?> clazz, ResultSetMetaData metaData) throws SQLException {
        Map<Integer, Method> columnMethodMap = Maps.newHashMap();
        Map<String, Method> methodMap = Maps.newHashMap();
        Method[] methods = clazz.getMethods(); 
        for(int i = 0; i < methods.length; i++) {
            String methodName = methods[i].getName();
            if(methodName.startsWith("set") && methods[i].getParameterTypes().length == 1) {
                methodName = methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
                methodMap.put(methodName, methods[i]);
            }
        }
        for(int i = 1; i <= metaData.getColumnCount(); i++) {
            Method method = methodMap.get(metaData.getColumnLabel(i));
            if(method == null) {
                continue;
            }
            columnMethodMap.put(i, method);
        }
        return columnMethodMap;
    }
    
    private Object getValue(ResultSet result, Class<?> paramterType, int columnIndex) throws SQLException {
        if(result.getObject(columnIndex) == null && !paramterType.isPrimitive()) {
            return null;
        }
        if(paramterType.equals(int.class) || paramterType.equals(Integer.class)) {
            return result.getInt(columnIndex);
        }
        if(paramterType.equals(long.class) || paramterType.equals(Long.class)) {
            return result.getLong(columnIndex);
        }
        if(paramterType.equals(Byte.class) || paramterType.equals(byte.class)) {
            return result.getByte(columnIndex);
        }
        if(paramterType.equals(Short.class) || paramterType.equals(short.class)) {
            return result.getShort(columnIndex);
        }
        if(paramterType.equals(Boolean.class) || paramterType.equals(boolean.class)) {
            return result.getBoolean(columnIndex);
        }
        if(paramterType.equals(Float.class) || paramterType.equals(float.class)) {
            return result.getFloat(columnIndex);
        }
        if(paramterType.equals(Double.class) || paramterType.equals(double.class)) {
            return result.getDouble(columnIndex);
        }
        if(paramterType.equals(BigDecimal.class)) {
            return result.getBigDecimal(columnIndex);
        }
        return result.getObject(columnIndex);
    }
    
    private void addParamters(PreparedStatement stmm, Object ...params) throws SQLException {
        if(params != null && params.length != 0) {
            int i = 1;
            for(Object param : params) {
                if(param instanceof Integer) {
                    stmm.setInt(i, (Integer)param);
                } else if (param instanceof Long) {
                    stmm.setLong(i, (Long)param);
                } else if (param instanceof Byte) {
                    stmm.setByte(i, (Byte)param);
                } else if (param instanceof Boolean) {
                    stmm.setBoolean(i, (Boolean)param);
                } else if (param instanceof String) {
                    stmm.setString(i, (String) param);
                } else if(param instanceof Short) {
                    stmm.setShort(i, (Short) param);
                } else {
                    stmm.setObject(i, param);
                }
                i ++;
            }
        }
    }
    private void addParamters(PreparedStatement stmm, Collection<Object> params) throws SQLException {
        if(params != null && params.size() != 0) {
            int i = 1;
            for(Object param : params) {
                if(param instanceof Integer) {
                    stmm.setInt(i, (Integer)param);
                } else if (param instanceof Long) {
                    stmm.setLong(i, (Long)param);
                } else if (param instanceof Byte) {
                    stmm.setByte(i, (Byte)param);
                } else if (param instanceof Boolean) {
                    stmm.setBoolean(i, (Boolean)param);
                } else if (param instanceof String) {
                    stmm.setString(i, (String) param);
                } else if(param instanceof Short) {
                    stmm.setShort(i, (Short) param);
                } else {
                    stmm.setObject(i, param);
                }
                i ++;
            }
        }
    }
    
    protected List<T> execQueryObjects(String sql, Object ...params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        List<T> returnList = Lists.newArrayList();
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            while(result.next()) {
                T t = this.parse(result);
                returnList.add(t);
            }
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
        return returnList;
    }
    
    protected List<T> execQueryObjects(String sql, Collection<Object> params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        List<T> returnList = Lists.newArrayList();
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            while(result.next()) {
                T t = this.parse(result);
                returnList.add(t);
            }
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
        return returnList;
    }
    
    protected int execInsert(String sql, Object ...params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            return stmm.executeUpdate();
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int execInsert(String sql, Collection<Object> params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            return stmm.executeUpdate();
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int execInsertReturnId(String sql, String name, Object object, Object ...params ) throws Exception {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            int effectRows = stmm.executeUpdate();
            String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
            Method[] methods = object.getClass().getMethods();
            Method methodInvoke = null;
            for(Method method : methods) {
                if(method.getName().equals(methodName)) {
                    methodInvoke = method;
                }
            }
            if(methodInvoke != null) {
                Object id = this.getConnectionId(connection, methodInvoke.getParameterTypes()[0]);
                methodInvoke.invoke(object, id);
            }
            return effectRows;
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int execInsertReturnId(String sql, String name, Object object, Collection<Object> params ) throws Exception {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            int effectRows = stmm.executeUpdate();
            String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
            Method[] methods = object.getClass().getMethods();
            Method methodInvoke = null;
            for(Method method : methods) {
                if(method.getName().equals(methodName)) {
                    methodInvoke = method;
                }
            }
            if(methodInvoke != null) {
                Object id = this.getConnectionId(connection, methodInvoke.getParameterTypes()[0]);
                methodInvoke.invoke(object, id);
            }
            return effectRows;
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int execUpdate(String sql, Object ...params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            return stmm.executeUpdate();
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int execUpdate(String sql, Collection<Object> params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            return stmm.executeUpdate();
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int execDelete(String sql, Object ...params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            return stmm.executeUpdate();
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int execDelete(String sql, Collection<Object> params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            return stmm.executeUpdate();
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int selectCount(String sql, Object ...params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            result.next();
            return result.getInt(1);
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    protected int selectCount(String sql, Collection<Object> params) throws SQLException {
        PooledDatabaseConnection connection = this.getConnection();
        PreparedStatement stmm = null;
        try {
            stmm = connection.prepareStatement(sql);
            this.addParamters(stmm, params);
            ResultSet result = stmm.executeQuery();
            result.next();
            return result.getInt(1);
        } finally {
            DBUtil.close(stmm);
            if(TransactionContainer2.needAutoCommit()) {
                connection.pushConnection();
            }
        }
    }
    
    private PooledDatabaseConnection getConnection() {
        PooledDatabaseConnection connection = TransactionContainer2.getConnection();
        if(connection != null) {
            return connection;
        }
        
        DataSourceConnection dataSource = this.getClass().getAnnotation(DataSourceConnection.class);
        if(dataSource == null) {
            throw new RuntimeException(this.getClass().getSimpleName() + " do not has Connection Conf");
        }
        Class<? extends IConnectionConfiguration> connectionConf = dataSource.connection();
        connection = DatabaseConnectionPool.getPooledConnection(connectionConf);
        if(connection == null) {
            throw new RuntimeException("can not get db connection");
        }
        
        if(!TransactionContainer2.needAutoCommit()) {
            try {
                connection.setAutoCommit(false);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            TransactionContainer2.setConnection(connection);
        }
        return connection;
    }
    
    private Object getConnectionId(PooledDatabaseConnection conn, Class<?> type) throws SQLException {
        String idQuery = "select @@Identity";
        PreparedStatement idQuerySttmt = conn.prepareStatement(idQuery);
        try {
            ResultSet idQueryRs = idQuerySttmt.executeQuery();
            idQueryRs.next();
            return getValue(idQueryRs, type, 1);
        } finally {
            DBUtil.close(idQuerySttmt);
        }
        
    }
    
    protected abstract T parse(ResultSet result) throws SQLException;
}
原文地址:https://www.cnblogs.com/lhp2012/p/9132597.html