尚硅谷JDBC實(shí)戰(zhàn)教程(2023最新版jdbc,JDK17+MySQL8)

package com.lyb.utils; import org.junit.Test; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.sql.*; import java.util.ArrayList; import java.util.List; public class BaseDao { /* 對(duì)非DQL的封裝 */ public int executeUpdate(String sql, Object... params) throws SQLException { Connection connection = DruidUtils.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 1; i <= params.length; i++) {//注意從一開(kāi)始,因?yàn)閰?shù)就是從1開(kāi)始。 preparedStatement.setObject(i, params[i - 1]);//注意這里要i-1 } int i = preparedStatement.executeUpdate(); //是否回收連接,需要考慮是不是事務(wù) if (connection.getAutoCommit()) {//如果自動(dòng)提交的話,沒(méi)有事務(wù),則我們關(guān)閉連接 DruidUtilsV2.CloseConnection(); } //如果是手動(dòng)提交的話,交給業(yè)務(wù)層去關(guān)閉。 return i; } /** * 對(duì)DQL的封裝 *將查詢結(jié)果封裝到實(shí)體類集合。 * @param clazz 查詢結(jié)果集對(duì)應(yīng)的實(shí)體類的class對(duì)象 * @param sql 查詢語(yǔ)句,要求列名或者別名等于實(shí)體類的屬性名。 u_id as id => id * @param params 占位符的值,用來(lái)替換? * @return 查詢的實(shí)體類集合 * @param <T> 結(jié)果的類型。 * @throws Exception */ public <T> List<T> executeQuery(Class<T> clazz, String sql, Object... params) throws Exception {//Class對(duì)象是用反射造對(duì)象 Connection connection = DruidUtilsV2.getConnection();//1.2.用工具類注冊(cè)驅(qū)動(dòng)并創(chuàng)建連接對(duì)象 PreparedStatement preparedStatement = connection.prepareStatement(sql);//3.創(chuàng)建PreparedStatement對(duì)象 //4.SQL語(yǔ)句是由外部傳入的sql if (params != null && params.length != 0) {//判斷方法傳入的參數(shù)是否滿足條件后,5.占位符賦值 for (int i = 1; i <= params.length; i++) {//根據(jù)占位符賦值的數(shù)量進(jìn)行占位符賦值 preparedStatement.setObject(i, params[i - 1]);//因?yàn)檎嘉环菑?開(kāi)始,所以上面i= 1開(kāi)始. //傳入的值的數(shù)組是從params[0] 到 params[i-1] } } ResultSet resultSet = preparedStatement.executeQuery();//6.執(zhí)行SQL語(yǔ)句并返回結(jié)果集 //7.結(jié)果集解析 ResultSetMetaData metaData = resultSet.getMetaData();//ResultSetMetaData對(duì)象存儲(chǔ)了resultSet結(jié)果集的列名信息,數(shù)量等 int columnCount = metaData.getColumnCount();//獲取結(jié)果集中列的數(shù)量 List<T> list = new ArrayList<>();//返回的數(shù)組對(duì)象 while (resultSet.next()) {//next()一次是一行 Constructor<T> declaredConstructor = clazz.getDeclaredConstructor();//反射創(chuàng)建構(gòu)造器 declaredConstructor.setAccessible(true);//打破Private修飾限制 T t = declaredConstructor.newInstance(); //創(chuàng)建代表一行數(shù)據(jù)的實(shí)體類T的對(duì)象 //************到下面的*之間完成的是:將SQL語(yǔ)句獲得的結(jié)果集的一行數(shù)據(jù),對(duì)應(yīng)著賦值給一個(gè)實(shí)體類對(duì)象的各個(gè)屬性。 for (int i = 1; i <= columnCount; i++) {//對(duì)結(jié)果集的一行進(jìn)行列的遍歷 String columnLabel = metaData.getColumnLabel(i);//根據(jù)列的下標(biāo)獲取一行中對(duì)應(yīng)的列名 Object value = resultSet.getObject(i);//根據(jù)列的下標(biāo)獲取一行中對(duì)應(yīng)列的值 /* 看下面之前你要明白:結(jié)果集 和 原表是兩個(gè)表,我們是對(duì)結(jié)果集進(jìn)行解析,不是原表 而我們?cè)谕ㄟ^(guò)sql語(yǔ)句查詢獲取結(jié)果集時(shí),可以給結(jié)果集的每一列重新起一個(gè)別名。 另外:你要會(huì)如何用反射創(chuàng)建類的對(duì)象,獲得類的屬性以及給屬性賦值。 利用反射,根據(jù)類的屬性名獲取類的屬性,從而給上面創(chuàng)建的實(shí)體類對(duì)象t的屬性賦值。 那么怎么拿到類的屬性名呢? 如果類的屬性名和ResultSet結(jié)果集的列名相等,那么我們就可以用結(jié)果集的列名充當(dāng)類的屬性名,那怎么保證它們兩個(gè)相等呢? 有兩種方式: 方式1. 實(shí)體類T的屬性名和對(duì)應(yīng)原表的列名相同 方式2. 在執(zhí)行SQL語(yǔ)句生成結(jié)果集的時(shí)候,把結(jié)果集的列名起一個(gè)別名,讓別名和實(shí)體類的類名對(duì)應(yīng)相等,那么我們 就實(shí)現(xiàn)了 類的屬性名和ResultSet結(jié)果集的列名相等 這個(gè)條件。 */ Field declaredField = clazz.getDeclaredField(columnLabel);//獲得屬性,根據(jù)屬性名 declaredField.setAccessible(true);//打破Private修飾限制 declaredField.set(t,value);//給屬性賦值 //******************************** } list.add(t);//在結(jié)果集的next()循環(huán)中,每next()一次就是一行數(shù)據(jù),將這一行對(duì)應(yīng)的實(shí)體類對(duì)象t添加到list集合中 } if(connection.getAutoCommit()){//判斷一下,是否需要在Dao層關(guān)閉關(guān)閉,即是否開(kāi)啟了手動(dòng)提交事務(wù)。開(kāi)啟了就不關(guān)閉了,交給業(yè)務(wù)層關(guān)閉。 DruidUtilsV2.CloseConnection(); } return list; } }
標(biāo)簽: