2020 - 4 - 25 :更新了BaseDao
根據項目需要,我完善了修正了BaseDao類,同時還可以支持將Java的LocalDatetime類型存到MySQL數據庫中(對應類型datetime)
BaseDao
import java.math.BigDecimal;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 基礎的數據庫操作類
* 簡化通用的基礎的增刪改查的操作,與具體業務邏輯無關
* @author passerbyYSQ
*/
public class BaseDao {
public interface PackResult<T> {
// 將ResultSet回調給子類,讓子類來處理ResultSet中的數據
T onResultReturn(ResultSet rs) throws Exception;
}
/**
* 通用的查詢操作
* @param <T> 查詢返回的數據,基類中無法確定,需要通過泛型拋給子類
* @param sql sql語句(裏面有佔位符)
* @param pack 一個接口,該接口有個抽象方法將ResultSet回調給子類,讓子類來處理ResultSet中數據
* @param args 與佔位符一一對應的參數值
* @return 封裝後的查詢結果
*/
public static <T> T select(String sql, PackResult<T> pack, Object... args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
T result = null;
try {
conn = DruidHelper.getConnection();
pstmt = conn.prepareStatement(sql);
// 將參數設置到sql語句的佔位符中
setValue(pstmt, args);
//System.out.println(pstmt.toString());
resultSet = pstmt.executeQuery();
// 由於不同的表對應不同的實體類,在基類中無法實現將resultSet封裝成對應的實體類返回
// 故只能通過接口中的回調函數交給子類去實現
result = pack.onResultReturn(resultSet);
return result;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
DruidHelper.close(resultSet, pstmt, conn);
}
}
/**
* 獲取結果集數量
* @param from from部分,傳遞時不需要帶"from"。之所以傳遞from,而不是表名,是考慮到多表查詢
* @param where where部分,傳遞時不需要帶"where",裏面含有佔位符
* @param args 代替佔位符的參數值
* @return 記錄數
*/
public static int getCount(String from, String where, Object... args) {
String sql = "select count(*) from " + from + " where " + where;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
try {
conn = DruidHelper.getConnection();
pstmt = conn.prepareStatement(sql);
// 將參數設置到sql語句的佔位符中
setValue(pstmt, args);
resultSet = pstmt.executeQuery();
return resultSet.next() ? resultSet.getInt(1) : -1;
} catch (Exception e) {
e.printStackTrace();
return -1;
} finally {
DruidHelper.close(resultSet, pstmt, conn);
}
}
/**
* 插入記錄,比較適用於插入一條或幾條數據。不適合插入一個集合的數據
* @param sql sql語句(裏面有佔位符)
* @param args 與佔位符一一對應的參數值
* @return 受影響的行數
*/
public static int insertOrUpdateOrDelete(String sql, Object... args) {
Connection conn = null;
PreparedStatement pstmt = null;
int count = 0;
try {
conn = DruidHelper.getConnection();
pstmt = conn.prepareStatement(sql);
// 將參數設置到sql語句的佔位符中
setValue(pstmt, args);
//System.out.println(pstmt.toString());
// 受影響的行數
count = pstmt.executeUpdate();
return count;
} catch (Exception e) {
e.printStackTrace();
return -1;
} finally {
DruidHelper.close(pstmt, conn);
}
}
/**
* 插入一條記錄。如果主鍵是自增長的,返回該條記錄的id
* 注意:主鍵必須是自增長的!!!
* @param sql
* @param args
* @return
*/
public static int insertReturnId(String sql, Object... args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DruidHelper.getConnection();
pstmt = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
// 將參數設置到sql語句的佔位符中
setValue(pstmt, args);
//System.out.println(pstmt.toString());
pstmt.executeUpdate();
// 獲取最後插入的記錄的自增長id。修改是不會返回的
rs = pstmt.getGeneratedKeys();
return rs.next() ? rs.getInt(1) : 0;
} catch (Exception e) {
e.printStackTrace();
return -1;
} finally {
DruidHelper.close(rs, pstmt, conn);
}
}
// 將參數設置到sql語句的佔位符中
private static void setValue(PreparedStatement pstmt, Object... args) throws SQLException {
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof String) { // 主要
pstmt.setString(i + 1, (String) args[i]);
} else if (args[i] instanceof Integer) { // 主要
int num = (Integer) args[i];
pstmt.setInt(i + 1, num);
} else if (args[i] instanceof LocalDateTime) { // 主要
pstmt.setTimestamp(i + 1, Timestamp.valueOf((LocalDateTime) args[i]));
} else if (args[i] instanceof Date) { // 主要 ((Date) args[i]).getTime()
pstmt.setTimestamp(i + 1, new Timestamp(((Date) args[i]).getTime()));
} else if (args[i] instanceof BigDecimal) {
pstmt.setBigDecimal(i + 1, (BigDecimal) args[i]);
} else if (args[i] instanceof Double) {
pstmt.setDouble(i + 1, (Double) args[i]);
} else if (args[i] instanceof Float) {
pstmt.setFloat(i + 1, (Float) args[i]);
} else if (args[i] instanceof Boolean) {
pstmt.setBoolean(i + 1, (boolean) args[i]);
} else {
throw new RuntimeException("BaseDao類暫不支持set該數據類型");
}
}
}
}
DbConnector
package dao;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 數據庫連接類的封裝
* 用於簡化獲取數據庫連接和關閉數據庫連接的操作
* @author passerbyYSQ
*/
public class DbConnector {
private static String driver;
private static String url;
private static String user;
private static String password;
// public static void main(String[] args) {
// new DbConnector();
// }
/**
* 靜態代碼塊
* 配置信息的獲取和數據庫驅動的註冊,在第一次將JDBCUtil加載進內存時初始化一次即可
*/
static {
try {
ClassLoader classLoader = DbConnector.class.getClassLoader();
// Eclipse中該配置文件位於src下
URL resource = classLoader.getResource("JDBC.properties");
// 使用URLDecoder.decode()解決路徑中的空格和中文字符問題
String path = URLDecoder.decode(resource.getPath(), "utf-8");
Properties properties = new Properties();
// new BufferedInputStream(new FileInputStream(path))
// new BufferedReader(new FileReader(new File(path)))
properties.load(new BufferedInputStream(new FileInputStream(path)));
driver = properties.getProperty("driver");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
// 註冊數據庫驅動
Class.forName(driver);
System.out.println("註冊數據庫驅動");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取數據庫連接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
System.out.println("獲取數據庫連接");
return DriverManager.getConnection(url, user, password);
}
/**
* 釋放資源
* @param stmt 執行sql語句的對象
* @param conn 數據庫連接對象
*/
public static void close(Statement stmt, Connection conn) {
close(null, stmt, conn);
}
/**
* 釋放資源的重載形式
* @param rs 結果集對象
* @param stmt 執行sql語句的對象
* @param conn 數據庫連接對象
*/
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
BaseDao的使用
package test;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import dao.BaseDao;
public class TestBaseDao {
@Test
public void testSelect() {
String sql = "select * from user where sex = ?";
System.out.println(sql);
List<User> userList = BaseDao.select(sql, new BaseDao.PackResult<List<User>>() {
@Override
public List<User> onResultReturn(ResultSet rs) throws SQLException {
List<User> users = new ArrayList<>();
while (rs.next()) {
String name = rs.getString("name");
String sex = rs.getString("sex");
Long birthday = rs.getLong("birthday"); // 時間戳
// 由於密碼是隱私數據,所以我們不將密碼返回給前端頁面
users.add(new User(name, null, sex, birthday));
}
return users;
}
}, "男");
for(User user : userList) {
System.out.println(user);
}
}
// @Test
// public void testInsert() {
// String sql = "insert into user values(NULL, ?, ?, ?, NULL)";
// int count = BaseDao.insertOrUpdateOrDelete(sql, "efg", "123", "女");
// System.out.println(count);
// }
class User {
private String name;
private String password;
private String sex;
private Long birthday;
public User(String name, String password, String sex, Long birthday) {
this.name = name;
this.password = password;
this.sex = sex;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Long getBirthday() {
return birthday;
}
public void setBirthday(Long birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User [name=" + name + ", password=" + password + ", sex=" + sex + ", birthday=" + birthday + "]";
}
}
}
配置文件:JDBC.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/數據庫名稱?characterEncoding=UTF-8
user=用戶名
password=密碼