JDBC的增刪改-結(jié)果集的元數(shù)據(jù)-Class反射-JDBC查詢封裝
一、使用JDBC批量添加
? 知識點復(fù)習(xí):
?1、JDBC的六大步驟 (導(dǎo)入jar包, 加載驅(qū)動類,獲取連接對象, 獲取sql執(zhí)行器、執(zhí)行sql與并返回結(jié)果, 關(guān)閉數(shù)據(jù)庫連接)
2、?封裝了一個DBUtil 類, 通過讀取屬性文件的方式獲取 基礎(chǔ)連接信息。
3、?批量添加: 一次性可執(zhí)行多個添加記錄 ,將多個sql語句在當(dāng)前這次連接中執(zhí)行完畢。
// 設(shè)置部門集合
List<Dept> list = new ArrayList<>();
list.add(new Dept(60,"市場部","武漢市"));
list.add(new Dept(70,"研發(fā)部","武漢市"));
list.add(new Dept(80,"教學(xué)部","武漢市"));
//通過DBUtil獲取數(shù)據(jù)庫連接
Connection conn = DBUtil.getConn();
String sql="insert into dept(deptno,dname,loc) values (?,?,?)";
//獲取預(yù)編譯sql執(zhí)行器
PreparedStatement ps = conn.prepareStatement(sql);
//批量設(shè)置該條sql語句的 參數(shù)
for(Dept dept : list){
//設(shè)置參數(shù)
ps.setInt(1,dept.getDeptno());
ps.setString(2,dept.getDname());
ps.setString(3,dept.getLoc());
// 將設(shè)置好的參數(shù) 先放入批量添加的容器中
ps.addBatch();
// 對于完整的sql語句 可以用有參的
// ps.addBatch(sql);
}
// 執(zhí)行sql語句 返回每一行sql語句影響的行數(shù) ,
int [] counts = ps.executeBatch();
System.out.println("結(jié)果長度:"+ counts.length);
System.out.println("結(jié)果:"+ Arrays.toString(counts));
//關(guān)閉sql語句
DBUtil.closeAll(conn,ps,null);
二、結(jié)果集的元數(shù)據(jù):
columnCount 結(jié)果集的列數(shù)
columnName 列的名稱 // select columnName as columnLabel…
columnLabel 列的別名(label)
columnClassName 列在Java中對應(yīng)的類型(可配合Class.forName(String className)獲取Class類型的返回值)
columnType 列在數(shù)據(jù)庫中的類型(數(shù)值編號)
columnTypeName 列在數(shù)據(jù)庫中的類型名稱
columnDisplaySize 列大小
結(jié)果集(ResultSet)和結(jié)果集元數(shù)據(jù)(ResultSetMetaData)同為JDBC標(biāo)準(zhǔn)中的接口|標(biāo)準(zhǔn)。
java.sql.ResultSet
java.sql.ResultSetMetaData
三、Class反射
1、為什么需要使用反射
?由于之前創(chuàng)建對象的過程 ,是已知這個類,然后對類進(jìn)行編譯,編譯通過之后才可以創(chuàng)建對象, 現(xiàn)在可能出現(xiàn) “未知的類” 只有“包名+類名” ,在運行期間才知道 該類是否存在,并動態(tài)創(chuàng)建該類的對象。 這時 創(chuàng)建對象的過程 可以通過反射的方式 完成。
?反射機(jī)制的定義: 對于任意一個類,都可以在運行期間,動態(tài)的創(chuàng)建該類的對象,能知曉該對象的屬性和方法,并動態(tài)調(diào)用屬性 和方法 ,這個過程就是Java的反射機(jī)制
?對于任意類 都存在一個該類的Class類型 ,如何獲取類的Classs類型
方式一: Class cls = Class.forName("類的全類名")
方式二: Class cls = 類名.class;
方式三: Class cls = 類的對象名.getClass()
常用API
Construct:
?cls.getConstructor(int.class , String.class); 根據(jù)參數(shù)類型和個數(shù) 獲取cls 對應(yīng)的 構(gòu)造器對象
Field : 屬性對應(yīng)的類型
?getDeclareFields () : 獲取所有聲明的屬性 (包括 任何修飾符,不包括private修飾)
?getFields(): 獲取所有聲明的public修飾的屬性
getDeclareFiled(String name): 根據(jù)屬性名獲取屬性對象
getField(String name):根據(jù)屬性名獲取屬性對象 (必須是共有的 )
Method : 方法對應(yīng)的類型
?getDeclaredMethods() : 返回當(dāng)前類的自己聲明的方法
?getMethods() :返回所有的方法(包括父類的)
?invoke(obj,參數(shù)值) :調(diào)用該方法
?getMethod(“方法名” ,參數(shù)值):根據(jù)方法名返回Method
四、反射封裝(增刪改查)
preparedStatement的作用:
1、提前傳入sql,執(zhí)行的時候,不傳入sql
2、支持傳入sql中的參數(shù)
3、解決sql注入邏輯漏洞
4、提高執(zhí)行效率
Object ...params(可變形參數(shù)組) 作用:在調(diào)用函數(shù)時,可以傳入任意個任意類型的參數(shù)
標(biāo)題查詢多行的封裝
//查詢多行多列
public static <T> List<T> list(String sql,Class<T> c,Object...params){
//創(chuàng)建一個集合,存放所有的對象
List<T> tList=new ArrayList<>();
try {
//1、注冊驅(qū)動-反射去加載jar包中com.mysql.jdbc.Driver這個類中的 DriverManager.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
//2、獲取連接對象
var conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/summer-camp2023?characterEncoding=utf8", "root", "admin");
//3、定義sql
//4、需要創(chuàng)建statement
var st = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
st.setObject(i+1,params[i]);
}
//5、statement 執(zhí)行sql,返回 結(jié)果集
var rs = st.executeQuery();
//結(jié)果集rs得到結(jié)果集元數(shù)據(jù)
ResultSetMetaData md=rs.getMetaData();
//獲取結(jié)果集總列數(shù)
var columnCount = md.getColumnCount();
//6、解析rs
while (rs.next()) {//rs.next 讀取結(jié)果集的光標(biāo)向下移動一行,光標(biāo)默認(rèn)在哪一行,列名所在的那一行
//根據(jù)每一行數(shù)據(jù),封裝成一個實體對象
T t = c.newInstance();
// 1、取出某一行的每個數(shù)據(jù),封裝到對象t的屬性中
for (int i = 1; i <= columnCount; i++) {
//通過列的序號,獲取每一列的值
var value = rs.getObject(i);
if (value!=null){
//通過列的序號,獲取每一列的列名
var columnName = md.getColumnName(i);
//因為列名和實體類t中的屬性名一致,為每一個屬性構(gòu)造一個反射中的set方法
var f = c.getDeclaredField(columnName);
//賦予私有屬性的賦值權(quán)限
f.setAccessible(true);
//使用反射,把value給到對象t的屬性中
f.set(t,value);//理解為:把value賦值給對象t的ColumName,相當(dāng)于set方法
}
}
//把對象存入集合中
tList.add(t);
}
//7、關(guān)閉資源
st.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
return tList;
}
查詢一行的封裝
//查詢一行
public static <T> T selectRow(String sql,Class<T> c,Object...params){
//創(chuàng)建一個集合,存放所有的對象
List<T> tList=new ArrayList<>();
try {
//1、注冊驅(qū)動-反射去加載jar包中com.mysql.jdbc.Driver這個類中的 DriverManager.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
//2、獲取連接對象
var conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/summer-camp2023?characterEncoding=utf8", "root", "admin");
//3、定義sql
//4、需要創(chuàng)建statement
var st = conn.prepareStatement(sql);
//執(zhí)行前給sql傳遞參數(shù)
for (int i = 0; i < params.length; i++) {
st.setObject(i+1,params[i]);
}
//5、statement 執(zhí)行sql,返回 結(jié)果集
var rs = st.executeQuery();
//結(jié)果集rs得到結(jié)果集元數(shù)據(jù)
ResultSetMetaData md=rs.getMetaData();
//獲取結(jié)果集總列數(shù)
var columnCount = md.getColumnCount();
//根據(jù)每一行數(shù)據(jù),封裝成一個實體對象
//6、解析rs
T t=null;
if (rs.next()) {//rs.next 讀取結(jié)果集的光標(biāo)向下移動一行,光標(biāo)默認(rèn)在哪一行,列名所在的那一行
t = c.newInstance();
// 1、取出某一行的每個數(shù)據(jù),封裝到對象t的屬性中
for (int i = 1; i <= columnCount; i++) {
//通過列的序號,獲取每一列的值
var value = rs.getObject(i);
if (value!=null){
//通過列的序號,獲取每一列的列名
var columnName = md.getColumnName(i);
//因為列名和實體類t中的屬性名一致,為每一個屬性構(gòu)造一個反射中的set方法
var f = c.getDeclaredField(columnName);
//賦予私有屬性的賦值權(quán)限
f.setAccessible(true);
//使用反射,把value給到對象t的屬性中
f.set(t,value);//理解為:把value賦值給對象t的ColumName,相當(dāng)于set方法
}
}
}
//7、關(guān)閉資源
st.close();
conn.close();
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
查詢一列的封裝
//查詢一列
public static <T> List<T> selectColumn(String sql,Class<T> c,Object...params){
//創(chuàng)建一個集合,存放所有的對象
List<T> tList=new ArrayList<>();
try {
//1、注冊驅(qū)動-反射去加載jar包中com.mysql.jdbc.Driver這個類中的 DriverManager.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
//2、獲取連接對象
var conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/summer-camp2023?characterEncoding=utf8", "root", "admin");
//3、定義sql
//4、需要創(chuàng)建statement
var st = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
st.setObject(i+1,params[i]);
}
//5、statement 執(zhí)行sql,返回 結(jié)果集
var rs = st.executeQuery();
//結(jié)果集rs得到結(jié)果集元數(shù)據(jù)
ResultSetMetaData md=rs.getMetaData();
//獲取結(jié)果集總列數(shù)
var columnCount = md.getColumnCount();
//6、解析rs
while (rs.next()) {//rs.next 讀取結(jié)果集的光標(biāo)向下移動一行,光標(biāo)默認(rèn)在哪一行,列名所在的那一行
//通過列的序號,獲取每一列的值
T t = (T) rs.getObject(1);
//把對象存入集合中
tList.add(t);
}
//7、關(guān)閉資源
st.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
return tList;
}
查詢單個的封裝
//查詢單個
public static <T> T selectOne(String sql,Class<T> c,Object...params){
try {
//1、注冊驅(qū)動-反射去加載jar包中com.mysql.jdbc.Driver這個類中的 DriverManager.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
//2、獲取連接對象
var conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/summer-camp2023?characterEncoding=utf8", "root", "admin");
//3、定義sql
var st = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
st.setObject(i+1,params[i]);
}
//5、statement 執(zhí)行sql,返回 結(jié)果集
var rs = st.executeQuery();
//結(jié)果集rs得到結(jié)果集元數(shù)據(jù)
ResultSetMetaData md=rs.getMetaData();
//獲取結(jié)果集總列數(shù)
var columnCount = md.getColumnCount();
//6、解析rs
T t=null;
if (rs.next()) {
t = (T) rs.getObject(1);
}
//7、關(guān)閉資源
st.close();
conn.close();
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
增刪改封裝方法
//增刪改
public static int update(String sql,Object...params){
try {
//1、注冊驅(qū)動-反射去加載jar包中com.mysql.jdbc.Driver這個類中的 DriverManager.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
//2、獲取連接對象
var conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/summer-camp2023?characterEncoding=utf8", "root", "admin");
//3、定義sql
//4、需要創(chuàng)建statement
var st = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
st.setObject(i+1,params[i]);
}
//5、statement 執(zhí)行sql,返回 結(jié)果集
var i = st.executeUpdate();
//7、關(guān)閉資源
st.close();
conn.close();
return i;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
總的來說,封裝只是為了讓代碼變得更簡潔,為后面的開發(fā)做鋪墊!

浙公網(wǎng)安備 33010602011771號