自己动手来封装jdbc访问类库
在公司开发项目(ssh框架)的时候,我特别烦躁的一点就是每次用jdbc方式写一个数据访问(hibernate 可以用但是个人觉得对于复杂查询难以做到和好的控制,可能自己还要慢慢研究吧,自己喜欢mybatis),每次都要写一大堆模板代码,比较繁琐!
下面说下我的思路。
第一步,分析抽象
从已有的代码,出发会发现,访问数据库的套路
-->读取配置文件(不是必须的,但是项目中这样做,当然可以tomcat配置数据源之类的啊)
-->获取Connection
-->获取statement或者preparestatement
--->编写你的sql(这里说一下,如果你用的statement这里直接凭借字符,如果用的preparestatement就是设置参数,以后的sql语句最好不要用statement,因为他很不安全!!一个很大的问题的sql注入!no zuo no die!)
-->执行sql命令
-->封装结果
-->返回数据
所以,抽象出来,需要做的是
1.抽象出执行查询和执行更新(update,insert,delete)
2.抽象结果处理
主要完成的就是着两个问题
第二步,接上一步编写执行sql的函数
1.sql执行方法
/**
* 执行sql
* @param sql sql文
* @param params 参数
* @return
*/
public static boolean executeSQL(String sql,String...params){
boolean flag = false;
Connection connection = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
for(int i = 0,n = params.length;i<n;i++){
statement.setString(i+1, params[i]);
}
statement.execute(sql);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}finally {
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return flag;
}
2.sql的查询方法
* 查询结果
* @param sql sql文
* @param params 参数
* @param handler 结果处理集
* @return 返回结果集
*/
public static<T> List<?> queryResult(String sql,String[] params,ResultMapper<T> handler,Class<T> c){
List<Map<String,Object>> results = null;
Connection connection = null;
ResultSet resultSet = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0, n = (params!=null?params.length:0); i < n; i++) {
statement.setString(i, params[i]);
}
resultSet = statement.executeQuery();
if(resultSet!=null){
results = new ArrayList<>();
String[] name = null;
ResultSetMetaData rsm = null;
while(resultSet.next()){
if(rsm==null){
rsm = resultSet.getMetaData();
System.out.println(JSON.toJSONString(rsm));
int count = rsm.getColumnCount();
System.out.println(count);
name = new String[count];
for(int i = 0;i<count;i++){
name[i] = rsm.getColumnName(i+1);
}
}
Map<String, Object> map = new HashMap<>();
// 开始填充值
for(String keys:name){
map.put(keys, resultSet.getString(keys));
}
results.add(map);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 开始处理结合
List<T> lists = new ArrayList<>();
if(results!=null){
for(Map<String, Object> e:results){
T t = (T) handler.convert(e,c);
lists.add(t);
}
return lists;
}else{
return null;
}
}
第三步,编写数据映射接口和默认实现类
package com.handkoo.dao;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
public class DButils<T> {
private static final Logger logger = LoggerFactory.getLogger(DButils.class);
private static String url = "";
private static String user = "";
private static String password = "";
static {
InputStream inputStream = DButils.class.getResourceAsStream("/jdbc.properties");
Properties properties = new Properties();
try {
properties.load(inputStream);
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
/**
* 执行sql
*
* @param sql
* sql文
* @param params
* 参数
* @return
*/
public static boolean executeSQL(String sql, String... params) {
boolean flag = false;
Connection connection = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0, n = params.length; i < n; i++) {
statement.setString(i + 1, params[i]);
}
statement.execute(sql);
flag = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return flag;
}
/**
* 查询结果
*
* @param sql
* sql文
* @param params
* 参数
* @param handler
* 结果处理集
* @return 返回结果集
*/
public static <T> List<?> queryResult(String sql, String[] params, ResultMapper<T> handler, Class<T> c) {
List<Map<String, Object>> results = null;
Connection connection = null;
ResultSet resultSet = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0, n = (params != null ? params.length : 0); i < n; i++) {
statement.setString(i+1, params[i]);
}
resultSet = statement.executeQuery();
if (resultSet != null) {
results = new ArrayList<>();
String[] name = null;
ResultSetMetaData rsm = null;
while (resultSet.next()) {
if (rsm == null) {
rsm = resultSet.getMetaData();
System.out.println(JSON.toJSONString(rsm));
int count = rsm.getColumnCount();
System.out.println(count);
name = new String[count];
for (int i = 0; i < count; i++) {
name[i] = rsm.getColumnName(i + 1);
}
}
Map<String, Object> map = new HashMap<>();
// 开始填充值
for (String keys : name) {
map.put(keys, resultSet.getString(keys));
}
results.add(map);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 开始处理结合
List<T> lists = new ArrayList<>();
if (results != null) {
for (Map<String, Object> e : results) {
T t = (T) handler.convert(e, c);
lists.add(t);
}
return lists;
} else {
return null;
}
}
/**
* 类型转化接口
*
* @author PengChan
*
* @param <T>
*/
public interface ResultMapper<T> {
@SuppressWarnings("hiding")
<T> T convert(Map<String, Object> resource, Class<T> c);
}
/**
* 默认的类型实现
*
* @author PengChan
*
*/
public class DefaultMapper implements ResultMapper<T> {
@SuppressWarnings("hiding")
public <T> T getInstance(Class<T> c) throws InstantiationException, IllegalAccessException {
return c.newInstance();
}
/**
* 转化的核心方法
*/
@SuppressWarnings("hiding")
@Override
public <T> T convert(Map<String, Object> resource, Class<T> c) {
T t = null;
try {
t = getInstance(c);
// 获取所有的成员变量
Field[] declaredFields = t.getClass().getDeclaredFields();
// 循环遍历设置值
for (Field f : declaredFields) {
setValute(f, t, resource.get(f.getName()));
}
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
/**
* 设置类型的值
*
* @param fieldType
* @param value
*/
@SuppressWarnings({ "hiding", "rawtypes" })
private <T> void setValute(Field field, T t, Object value) {
try {
Class fieldType = field.getType();
field.setAccessible(true);
if (fieldType.equals(int.class)) {// 如果是整形
field.setInt(t, (int) value);
} else if (fieldType.equals(float.class)) {
field.setFloat(t, (float) value);
} else if (fieldType.equals(boolean.class)) {
field.setBoolean(t, (boolean) value);
} else if (fieldType.equals(double.class)) {
field.setDouble(t, (double) value);
} else if (fieldType.equals(byte.class)) {
field.setByte(t, (byte) value);
} else if (fieldType.equals(short.class)) {
field.setShort(t, (short) value);
} else if (fieldType.equals(long.class)) {
field.setLong(t, (long) value);
} else if (fieldType.equals(char.class)) {
field.setChar(t, (char) value);
} else {
field.set(t, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
调用方式:
DButils.queryResult(sql, null, new DButils().new DefaultMapper(), FitType.class);
注意:该工具类有一个局限性,就是对应的java类的属性名称需要与数据库的名称一致才能匹配。(如果这样,还需要配置xml文件来建立实体类和数据库表之间的映射,这不在考虑的范围之内,建议使用mybatis)
运行的结果如下:
以上就是我全部的分析内容了,有的地方还需要完善。