万能 CURD 接口
在实际的使用时,经常遇到这么一个问题,我要从某种数据库中查询出数据,但是不告诉你字段/属性。
乍一看,这个怎么可能,不告诉我字段/属性,要把数据查出来,后来在github上看见一段代码,读了这段代码后恍然大悟。还是 too young to simple
原理是通过JDBC的getMetaData()方法来获取表结构,里面用到了反射 (进行了处理,高并发下还是不建议使用)
比较重要的一点是查询的时候数据库有数据字典,可以根据数据字典获取所有字段/属性
实测,MySQL 可用
代码如下
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* 通用接口<br>
*
* @author weikeqin.cn@gmail.com
* @version V1.0
* @date 2017-07-11 15:12
*/
public interface Executor {
/**
* 查询接口
*
* @param sql 查询语句
* @param params 占位符对应的参数
* @param conn 连接
* @return Iterator<LinkedHashMap<String, Object>>
* @throws SQLException
*/
Iterator<Map<String, Object>> query(String sql, Map<Integer, Object> params, Connection conn) throws SQLException;
/**
* (单条)增删改接口
*
* @param sql 增删改语句
* @param params 占位符对应的参数
* @param conn 连接
* @return 操作的条数
* @throws SQLException
*/
int operat(String sql, Map<Integer, Object> params, Connection conn) throws SQLException;
/**
* 批量操作<br>
* 大于等于0是成功处理的
*
* @param sql 增删改语句
* @param list 占位符对应的参数
* @param conn 连接
* @return
* @throws SQLException
* @author : weikeqin.cn@gmail.com
* @date : 2017-09-08 14:47:15
*/
int[] betchOperat(String sql, List<Map<Integer, Object>> list, Connection conn) throws SQLException;
}
import java.sql.*;
import java.util.*;
/**
* @author weikeqin.cn@gmail.com
* @version V1.0
* @date 2017-07-11 15:31
*/
public class ExecutorImpl implements Executor {
/**
* @param sql 查询语句
* @param params 占位符 参数
* @param conn 连接
* @return
*/
@Override
public Iterator<Map<String, Object>> query(String sql, Map<Integer, Object> params,
Connection conn) throws SQLException {
final PreparedStatement statement = conn.prepareStatement(sql);
// 设置参数
setParameters(statement, params);
// 执行查询并获得结果
final ResultSet result = statement.executeQuery();
// 封装返回
return new Iterator<Map<String, Object>>() {
boolean hasNext = result.next();
// 所有字段
public List<String> columns;
// 字段个数
public int columnsCount;
/**
*
*
* @return
*/
@Override
public boolean hasNext() {
return hasNext;
}
/**
* 获得所有字段<br>
* 第一次会查询出所有字段,第二 第三次 直接用columns
*
* @return
* @throws SQLException
*/
private List<String> getColumns() throws SQLException {
if (columns != null) {
return columns;
}
ResultSetMetaData metaData = result.getMetaData();
// 查询出的字段
int count = metaData.getColumnCount();
List<String> cols = new ArrayList<>(count);
for (int i = 1; i <= count; i++) {
cols.add(metaData.getColumnName(i));
}
columnsCount = cols.size();
return columns = cols;
}
/**
*
* @return
*/
@Override
public Map<String, Object> next() {
try {
if (hasNext) {
//
Map<String, Object> map = new LinkedHashMap<>(columnsCount);
for (String col : getColumns()) {
map.put(col, result.getObject(col));
}
hasNext = result.next();
if (!hasNext) {
result.close();
statement.close();
}
return map;
} else {
throw new NoSuchElementException();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
*
*/
@Override
public void remove() {
}
};
}
/**
* 增删改操作
*
* @param sql 增删改语句
* @param params 占位符参数
* @param conn 连接
* @return
* @throws SQLException
*/
@Override
public int operat(String sql, Map<Integer, Object> params, Connection conn) throws SQLException {
PreparedStatement statement = conn.prepareStatement(sql);
setParameters(statement, params);
int count = statement.executeUpdate();
statement.close();
return count;
}
/**
* 大于等于0是成功处理的
*
* @param sql
* @param list
* @param conn
* @author : weikeqin.cn@gmail.com
* @date : 2017-09-08 14:48:50
*/
@Override
public int[] betchOperat(String sql, List<Map<Integer, Object>> list, Connection conn)
throws SQLException {
conn.setAutoCommit(false);
PreparedStatement statement = conn.prepareStatement(sql);
int size = list.size();
for (int i = 0; i < size; i++) {
// 一条语句里的多个占位符参数
Map<Integer, Object> map = list.get(i);
setParameters(statement, map);
statement.addBatch();
}
int[] array = statement.executeBatch();
conn.commit();
statement.close();
return array;
}
/**
* 赋值 给占位符赋值
*
* @param statement
* @param params
* @throws SQLException
* @author weikeqin.cn@gmail.com
*/
private void setParameters(PreparedStatement statement, Map<Integer, Object> params)
throws SQLException {
// 校验
if (params == null || params.isEmpty()) {
return;
}
for (Map.Entry<Integer, Object> entry : params.entrySet()) {
statement.setObject(entry.getKey(), entry.getValue());
}
} // end method
}