数据库操作通用类
内容:完成基本的CURD操作,其中查询语句返回的是List<Object[]>,需要在手动将Object[]转为需要的Entity。
优点:达到了sql防注入,并且,将对数据库的操作独立开来,可以提高内聚,降低耦合。达到了哪里使用,哪里关闭的效果,避免隐患。
升级版(反射自动注入)
查询利用反射,自动匹配相同查询结果进行字段注入。
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JdbcUtilV2 {
/**
* 定义需要的变量
*/
private static Connection connection = null;
/**
* 在大多情况下,我们使用的是PrepardStatement 来代替Statement
* 这样可以防止sql注入
*/
private static PreparedStatement preparedStatement = null;
private static ResultSet resultSet = null;
/**
* 连接数据库参数
*/
private static String username = "";
private static String password = "";
private static String driver = "";
private static String url = "";
/**
* 加载驱动,只需一次
*/
static {
try {
username = "root";
password = "密码";
driver = "com.mysql.jdbc.Driver";
url = "jdbc:mysql://localhost:3306/mybatisDB01?characterEncoding=utf8&useSSL=false";
Class.forName(driver);
} catch (Exception e) {
System.err.println("连接失败,请检查连接参数");
e.printStackTrace();
}
}
/**
* 获取数据库连接
*
* @return 返回Connection
*/
private static Connection getConnection() {
try {
connection = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
System.err.println("获取连接失败");
e.printStackTrace();
}
return connection;
}
public <T> List<T> query(String sql, Class<T> clazz, Object ...params){
try {
//获取连接
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);
//对sql中的占位符进行赋值
setPreparedStatement(params);
//获得结果集合
resultSet = preparedStatement.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
//定义List存放每行数据
List<T> tList = new ArrayList<>();
//获取列数
int columnCount = metaData.getColumnCount();
//对结果集合进行遍历并将每行的数据存入Object[]中
while (resultSet.next()) {
//对象数组,表示一行数据
T t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
Object value = resultSet.getObject(i + 1);
if(value == null){continue;}
Field field = clazz.getDeclaredField(metaData.getColumnLabel(i + 1));
field.setAccessible(true);
field.set(t, value);
}
//将数组存入list
tList.add(t);
}
return tList;
}catch (Exception e){
System.err.println("查询失败!");
e.printStackTrace();
} finally {
close();
}
return null;
}
/**
* 可处理insert/delete/update语句
* @param sql sql语句
* @param params 占位符参数数组
* @return 返回bool值,表示是否成功
*/
public boolean execute(String sql, Object ...params){
try {
//获取连接
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);
//对占位符进行赋值
setPreparedStatement(params);
//提交sql
preparedStatement.executeUpdate();
return true;
} catch (Exception e){
System.err.println("表更新失败!");
e.printStackTrace();
} finally {
close();
}
return false;
}
/**
* 对sql语句中的占位符进行赋值
* @param params 参数值
* @throws SQLException sql异常
*/
private void setPreparedStatement(Object ... params) throws SQLException {
if(params != null && params.length > 0){
for(int i = 0; i < params.length; i++){
if("null".equals(params[i])){
preparedStatement.setNull(i + 1, Types.NULL);
}else{
preparedStatement.setObject(i + 1, params[i]);
}
}
}
}
/**
* 关闭资源的函数
*/
private void close() {
if(resultSet != null) {
try {
resultSet.close();
} catch (Exception e) {
e.printStackTrace();
}
resultSet = null;
}
if(preparedStatement != null) {
try {
preparedStatement.close();
} catch (Exception e) {
e.printStackTrace();
}
preparedStatement = null;
}
if(connection != null) {
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
connection = null;
}
}
}
使用案例
public class Card {
private Integer id;
private String code;
//...getter/setter
}
查询记录
【注】查询结果的字段别名必须与实体类的参数名称一致,例如数据库的card字段为id,code_sn
,实体类Card参数为id,code
,则查询时,code_sn
必须起别名code_sn AS code
public void test01(){
//sql语句
String sql = "select id, code_sn AS code from idencard";
//获取查询结果list
List<Card> cardList = jdbcUtilV2.query(sql, Card.class);
}
public void test02(){
//sql语句
String sql = "select id, code_sn AS code from idencard where id = ?";
//获取查询结果list
List<Card> cardList = jdbcUtilV2.query(sql, Card.class, 5);
}
插入语句
【注】可自动处理null值
public void test03(){
String sql = "insert into idencard values(?, ?)";
if(jdbcUtilV2.execute(sql, "null", "7283498127391")){
System.out.println("ok");
} else{
System.out.println("error");
}
}
旧版
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JdbcUtil {
/**
* 定义需要的变量
*/
private static Connection connection = null;
/**
* 在大多情况下,我们使用的是PrepardStatement 来代替Statement
* 这样可以防止sql注入
*/
private static PreparedStatement preparedStatement = null;
private static ResultSet resultSet = null;
/**
* 连接数据库参数
*/
private static String username = "";
private static String password = "";
private static String driver = "";
private static String url = "";
/**
* 加载驱动,只需一次
*/
static {
try {
username = "root";
password = "密码";
driver = "com.mysql.jdbc.Driver";
url = "jdbc:mysql://localhost:3306/你的数据库名?characterEncoding=utf8&useSSL=false";
Class.forName(driver);
} catch (Exception e) {
System.err.println("连接失败,请检查连接参数");
e.printStackTrace();
}
}
/**
* 获取数据库连接
* @return 返回Connection
*/
private static Connection getConnection() {
try {
connection = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
System.err.println("获取连接失败");
e.printStackTrace();
}
return connection;
}
/**
* 查询语句
* @param sql sql语句
* @param parms 占位符参数数组
* @return 返回List<Object[]>
*/
public List<Object[]> select(String sql, String[] parms) {
try {
//获取连接
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);
//对sql中的占位符进行赋值
setPreparedStatement(parms);
//获得结果集合
resultSet = preparedStatement.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
//定义List存放每行数据
List<Object[]> objectList = new ArrayList<>();
//获取列数
int columnCount = metaData.getColumnCount();
//对结果集合进行遍历并将每行的数据存入Object[]中
while (resultSet.next()) {
//对象数组,表示一行数据
Object[] objects = new Object[columnCount];
for (int i = 1; i <= columnCount; i++) {
objects[i - 1] = resultSet.getObject(i);
}
//将数组存入list
objectList.add(objects);
}
return objectList;
} catch (Exception e) {
System.err.println("查询失败!");
e.printStackTrace();
} finally {
close();
}
return null;
}
/**
* 可处理insert/delete/update语句
* @param sql sql语句
* @param parms 占位符参数数组
* @return 返回bool值,表示是否成功
*/
public boolean addOrInsertOrUpdate(String sql, String[] parms){
try {
//获取连接
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);
//对占位符进行赋值
setPreparedStatement(parms);
//提交sql
preparedStatement.executeUpdate();
return true;
} catch (Exception e){
System.err.println("表更新失败!");
e.printStackTrace();
} finally {
close();
}
return false;
}
/**
* 对sql语句中的占位符进行赋值
* @param parms 参数值
* @throws SQLException sql异常
*/
private void setPreparedStatement(String[] parms) throws SQLException {
if (parms != null && parms.length > 0) {
for (int i = 0; i < parms.length; i++) {
if("null".equals(parms[i])){
preparedStatement.setNull(i + 1, Types.NULL);
}else {
preparedStatement.setString(i + 1, parms[i]);
}
}
}
}
/**
* 关闭资源的函数
*/
private void close() {
if(resultSet != null) {
try {
resultSet.close();
} catch (Exception e) {
e.printStackTrace();
}
resultSet = null;
}
if(preparedStatement != null) {
try {
preparedStatement.close();
} catch (Exception e) {
e.printStackTrace();
}
preparedStatement = null;
}
if(connection != null) {
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
connection = null;
}
}
}
使用案例
查询记录
【注】如果sql语句中无占位符,则直接传入null即可
public void test01(){
//sql语句
String sql = "select * from idencard";
//获取查询结果list
List<Object[]> objectList = jdbcUtil.select(sql, null);
//待转换类型后数据的list
List<Card> cardList = new ArrayList<>();
//对返回的结果进行遍历
for (Object[] objects : objectList) {
//将Object[]转为自己的Entity
Card card = new Card();
card.setId((int)objects[0]);
card.setCard_sn(objects[1].toString());
//存入该类型的list中
cardList.add(card);
}
}
插入语句
【注】可自动处理null值
public void test02(){
String sql = "insert into idencard values(?, ?)";
String[] parms = {"null", "7283498127391"};
if(jdbcUtil.addOrInsertOrUpdate(sql, parms)){
System.out.println("ok");
} else{
System.out.println("error");
}
}
总结:可以看出,增删改的操作时大同小异的,可以总结使用方法,用在各个地方进行通用,不用多次编写重复代码。