说明:最近遇到了一个场景,功能代码开发完毕了,需要在本地测试,但是项目暂时还无法启动。又因为项目引入的依赖是Spring,而不是封装好的Spring Boot,我不知道怎么写测试类,装配Bean对象一直报NPE,百度一下说需要读取applicationContext.xml
文件,不知道是项目结构复杂还是怎么,试了下也还不行。
然后,我就考虑使用JDBC来操作数据库,而不用Mapper。为此,写了一个简易的JDBC工具类,大家可能根据自己需要进行复制,可以将数据库配置写在application.yml文件里,然后在代码里用@Value注解读取。个人认为查询方法最好用,可以传入一个VO对象,然后返回封装后的对象结果集,其他三个方法一模一样,只在用途上做区分。
另外,该工具类实现了蛇形命名(如create_id)转驼峰命名(createId)。当我在写的时候,频频报错,然后一一分析解决,我逐渐意识到,这不就是DAO框架要实现的事情嘛?
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author hezhongying
* @description jdbc工具类,用于测试
*/
public class SimpleJDBCUtils {
private static String driver = "com.mysql.jdbc.Driver";
private static String URL = "jdbc:mysql://127.0.01:3306/jdbc_test?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8";
private static String DB_USER = "root";
private static String DB_PASSWORD = "123456";
private static Connection conn = null;
/**
* 创建连接
*/
private static void createConnection() {
try {
Class.forName(driver);
conn = DriverManager.getConnection(URL, DB_USER, DB_PASSWORD);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
/**
* 关闭连接
*/
private static void closeConnection() {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 查询数据
*
* @param clazz 封装的实体类,如User.class
* @param sql 查询语句
* @param <T> 泛型
* @return 查询的结果集
*/
public static <T> List<T> selectData(Class<T> clazz, String sql) {
List<T> results = new ArrayList<>();
createConnection();
try {
Statement state = conn.createStatement();
ResultSet rs = state.executeQuery(sql);
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
while (rs.next()) {
T object = clazz.newInstance();
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnName(i);
String fieldName = convertSnakeCaseToCamelCase(columnName);
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, rs.getObject(columnName));
}
results.add(object);
}
rs.close();
state.close();
} catch (SQLException | NoSuchFieldException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
} finally {
closeConnection();
}
return results;
}
/**
* 删除数据
*/
public static int deleteData(String sql) {
int count;
createConnection();
try {
Statement state = conn.createStatement();
count = state.executeUpdate(sql);
state.close();
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
closeConnection();
}
return count;
}
/**
* 新增数据
*/
public static int insertData(String sql) {
int count;
createConnection();
try {
Statement state = conn.createStatement();
count = state.executeUpdate(sql);
state.close();
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
closeConnection();
}
return count;
}
/**
* 更新数据
*/
public static int updateData(String sql) {
int count;
createConnection();
try {
Statement state = conn.createStatement();
count = state.executeUpdate(sql);
state.close();
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
closeConnection();
}
return count;
}
/**
* 蛇形命名转驼峰命名
* 如 user_name -> userName
* @param input
* @return
*/
public static String convertSnakeCaseToCamelCase(String input) {
if (!input.contains("_")) {
return input;
}
StringBuilder result = new StringBuilder();
boolean nextUpperCase = false;
for (int i = 0; i < input.length(); i++) {
char currentChar = input.charAt(i);
if (currentChar == '_') {
nextUpperCase = true;
} else {
if (nextUpperCase) {
result.append(Character.toUpperCase(currentChar));
nextUpperCase = false;
} else {
result.append(Character.toLowerCase(currentChar));
}
}
}
return result.toString();
}
}