亚洲欧美日韩综合系列在线_91精品人妻一区二区_欧美大肥婆一级特大AA片_九色91视频免费观看_亚洲综合国产精品_av中文字幕在线不卡_久久精品色综合网_看黄色视频的软件_无卡无码高清中文字幕码2024_亚洲欧美日韩天堂网

利用Java針對MySql封裝的jdbc框架類 JdbcUtils 完整實現(xiàn)(包含增刪改查、JavaBean反射原理,附源碼)

來源:yanzi1225627 發(fā)布時間:2018-11-21 14:11:13 閱讀量:980

最近看老羅的視頻,跟著完成了利用Java操作MySql數(shù)據(jù)庫的一個框架類JdbcUtils.java,完成對數(shù)據(jù)庫的增刪改查。其中查詢這塊,包括普通的查詢和利用反射完成的查詢,主要包括以下幾個函數(shù)接口:


1、public Connection getConnection()   獲得數(shù)據(jù)庫的連接


2、public boolean updateByPreparedStatement(String sql, List<Object>params)throws SQLException  更新數(shù)據(jù)庫,包括增加記錄、刪除記錄、改動某個記錄三個功能。


3、public Map<String, Object> findSimpleResult(String sql, List<Object> params) throws SQLException 查詢單條記錄,傳進(jìn)去的是一個List<Object>參數(shù)填充占位符,返回的是一個Map<String, Object>.一個Map對應(yīng)一條完整的記錄,String對應(yīng)屬性名,Object是屬性值。


4、public List<Map<String, Object>> findModeResult(String sql, List<Object> params) throws SQLException 查詢多條記錄,放在List里。


上面四個函數(shù)已經(jīng)包括了MySQl的所有操作,完全能夠滿足使用需要。視頻里老羅還擴(kuò)展了兩個反射來查詢的函數(shù)。


5、public <T> T findSimpleRefResult(String sql, List<Object> params,

Class<T> cls )throws Exception   利用反射查詢單個記錄。


6、 public <T> List<T> findMoreRefResult(String sql, List<Object> params,

Class<T> cls )throws Exception   利用反射查詢多個記錄。


下面附完整代碼:


JdbcUtils.java



package com.jdbc.dbutils;

 

import java.lang.reflect.Field;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

 

import domain.UserInfo;

 

 

public class JdbcUtils {

//數(shù)據(jù)庫用戶名

private static final String USERNAME = "root";

//數(shù)據(jù)庫密碼

private static final String PASSWORD = "yanzi";

//驅(qū)動信息 

private static final String DRIVER = "com.mysql.jdbc.Driver";

//數(shù)據(jù)庫地址

private static final String URL = "jdbc:mysql://localhost:3306/mydb";

private Connection connection;

private PreparedStatement pstmt;

private ResultSet resultSet;

public JdbcUtils() {

// TODO Auto-generated constructor stub

try{

Class.forName(DRIVER);

System.out.println("數(shù)據(jù)庫連接成功!");

 

}catch(Exception e){

 

}

}

/**

* 獲得數(shù)據(jù)庫的連接

* @return

*/

public Connection getConnection(){

try {

connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return connection;

}

 

/**

* 增加、刪除、改

* @param sql

* @param params

* @return

* @throws SQLException

*/

public boolean updateByPreparedStatement(String sql, List<Object>params)throws SQLException{

boolean flag = false;

int result = -1;

pstmt = connection.prepareStatement(sql);

int index = 1;

if(params != null && !params.isEmpty()){

for(int i=0; i<params.size(); i++){

pstmt.setObject(index++, params.get(i));

}

}

result = pstmt.executeUpdate();

flag = result > 0 ? true : false;

return flag;

}

 

/**

* 查詢單條記錄

* @param sql

* @param params

* @return

* @throws SQLException

*/

public Map<String, Object> findSimpleResult(String sql, List<Object> params) throws SQLException{

Map<String, Object> map = new HashMap<String, Object>();

int index  = 1;

pstmt = connection.prepareStatement(sql);

if(params != null && !params.isEmpty()){

for(int i=0; i<params.size(); i++){

pstmt.setObject(index++, params.get(i));

}

}

resultSet = pstmt.executeQuery();//返回查詢結(jié)果

ResultSetMetaData metaData = resultSet.getMetaData();

int col_len = metaData.getColumnCount();

while(resultSet.next()){

for(int i=0; i<col_len; i++ ){

String cols_name = metaData.getColumnName(i+1);

Object cols_value = resultSet.getObject(cols_name);

if(cols_value == null){

cols_value = "";

}

map.put(cols_name, cols_value);

}

}

return map;

}

 

/**查詢多條記錄

* @param sql

* @param params

* @return

* @throws SQLException

*/

public List<Map<String, Object>> findModeResult(String sql, List<Object> params) throws SQLException{

List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

int index = 1;

pstmt = connection.prepareStatement(sql);

if(params != null && !params.isEmpty()){

for(int i = 0; i<params.size(); i++){

pstmt.setObject(index++, params.get(i));

}

}

resultSet = pstmt.executeQuery();

ResultSetMetaData metaData = resultSet.getMetaData();

int cols_len = metaData.getColumnCount();

while(resultSet.next()){

Map<String, Object> map = new HashMap<String, Object>();

for(int i=0; i<cols_len; i++){

String cols_name = metaData.getColumnName(i+1);

Object cols_value = resultSet.getObject(cols_name);

if(cols_value == null){

cols_value = "";

}

map.put(cols_name, cols_value);

}

list.add(map);

}

 

return list;

}

 

/**通過反射機(jī)制查詢單條記錄

* @param sql

* @param params

* @param cls

* @return

* @throws Exception

*/

public <T> T findSimpleRefResult(String sql, List<Object> params,

Class<T> cls )throws Exception{

T resultObject = null;

int index = 1;

pstmt = connection.prepareStatement(sql);

if(params != null && !params.isEmpty()){

for(int i = 0; i<params.size(); i++){

pstmt.setObject(index++, params.get(i));

}

}

resultSet = pstmt.executeQuery();

ResultSetMetaData metaData  = resultSet.getMetaData();

int cols_len = metaData.getColumnCount();

while(resultSet.next()){

//通過反射機(jī)制創(chuàng)建一個實例

resultObject = cls.newInstance();

for(int i = 0; i<cols_len; i++){

String cols_name = metaData.getColumnName(i+1);

Object cols_value = resultSet.getObject(cols_name);

if(cols_value == null){

cols_value = "";

}

Field field = cls.getDeclaredField(cols_name);

field.setAccessible(true); //打開javabean的訪問權(quán)限

field.set(resultObject, cols_value);

}

}

return resultObject;

 

}

 

/**通過反射機(jī)制查詢多條記錄

* @param sql 

* @param params

* @param cls

* @return

* @throws Exception

*/

public <T> List<T> findMoreRefResult(String sql, List<Object> params,

Class<T> cls )throws Exception {

List<T> list = new ArrayList<T>();

int index = 1;

pstmt = connection.prepareStatement(sql);

if(params != null && !params.isEmpty()){

for(int i = 0; i<params.size(); i++){

pstmt.setObject(index++, params.get(i));

}

}

resultSet = pstmt.executeQuery();

ResultSetMetaData metaData  = resultSet.getMetaData();

int cols_len = metaData.getColumnCount();

while(resultSet.next()){

//通過反射機(jī)制創(chuàng)建一個實例

T resultObject = cls.newInstance();

for(int i = 0; i<cols_len; i++){

String cols_name = metaData.getColumnName(i+1);

Object cols_value = resultSet.getObject(cols_name);

if(cols_value == null){

cols_value = "";

}

Field field = cls.getDeclaredField(cols_name);

field.setAccessible(true); //打開javabean的訪問權(quán)限

field.set(resultObject, cols_value);

}

list.add(resultObject);

}

return list;

}

 

/**

* 釋放數(shù)據(jù)庫連接

*/

public void releaseConn(){

if(resultSet != null){

try{

resultSet.close();

}catch(SQLException e){

e.printStackTrace();

}

}

}

 

/**

* @param args

*/

public static void main(String[] args) throws SQLException {

// TODO Auto-generated method stub

JdbcUtils jdbcUtils = new JdbcUtils();

jdbcUtils.getConnection();

 

/*******************增*********************/

/* String sql = "insert into userinfo (username, pswd) values (?, ?), (?, ?), (?, ?)";

List<Object> params = new ArrayList<Object>();

params.add("小明");

params.add("123xiaoming");

params.add("張三");

params.add("zhangsan");

params.add("李四");

params.add("lisi000");

try {

boolean flag = jdbcUtils.updateByPreparedStatement(sql, params);

System.out.println(flag);

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}*/

 

 

/*******************刪*********************/

//刪除名字為張三的記錄

/* String sql = "delete from userinfo where username = ?";

List<Object> params = new ArrayList<Object>();

params.add("小明");

boolean flag = jdbcUtils.updateByPreparedStatement(sql, params);*/

 

/*******************改*********************/

//將名字為李四的密碼改了

/* String sql = "update userinfo set pswd = ? where username = ? ";

List<Object> params = new ArrayList<Object>();

params.add("lisi88888");

params.add("李四");

boolean flag = jdbcUtils.updateByPreparedStatement(sql, params);

System.out.println(flag);*/

 

/*******************查*********************/

//不利用反射查詢多個記錄

/* String sql2 = "select * from userinfo ";

List<Map<String, Object>> list = jdbcUtils.findModeResult(sql2, null);

System.out.println(list);*/

 

//利用反射查詢 單條記錄

String sql = "select * from userinfo where username = ? ";

List<Object> params = new ArrayList<Object>();

params.add("李四");

UserInfo userInfo;

try {

userInfo = jdbcUtils.findSimpleRefResult(sql, params, UserInfo.class);

System.out.print(userInfo);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

 

}

 

}


根據(jù)上面代碼可以看到,數(shù)據(jù)庫名字:mydb,表名:userinfo,結(jié)構(gòu)如下:

+----------+-------------+------+-----+---------+----------------+

| Field    | Type        | Null | Key | Default | Extra          |

+----------+-------------+------+-----+---------+----------------+

| id       | int(11)     | NO   | PRI | NULL    | auto_increment |

| username | varchar(64) | YES  |     | NULL    |                |

| pswd     | varchar(64) | YES  |     | NULL    |                |

+----------+-------------+------+-----+---------+----------------+


是用Nvicat提前創(chuàng)建好的:




因為有兩個接口用到了反射,因此對應(yīng)的JavaBean UserInfo.java代碼如下:



package domain;

 

import java.io.Serializable;

 

public class UserInfo implements Serializable{

 

/**

*/

private static final long serialVersionUID = 1L;

 

private int id;

private String username;

private String pswd;

public UserInfo() {

// TODO Auto-generated constructor stub

}

 

public int getId() {

return id;

}

 

public void setId(int id) {

this.id = id;

}

 

public String getUsername() {

return username;

}

 

public void setUsername(String username) {

this.username = username;

}

 

public String getPswd() {

return pswd;

}

 

public void setPswd(String pswd) {

this.pswd = pswd;

}

 

@Override

public String toString() {

return "UserInfo [id=" + id + ", username=" + username + ", pswd="

+ pswd + "]";

}

 

 

 

 

 

}


補(bǔ)充說明:

1. 在安裝完mysql-connector-java-gpl-5.1.26.exe后會發(fā)現(xiàn)找不到j(luò)ar包,其實jar文件在C:\Program Files\MySQL\MySQL Connector J目錄下,有兩個jar包:




用哪一個都o(jì)k。在Java工程里新建一個文件夾libs,然后將mysql-connector-java-5.1.26-bin.jar拷貝過去,右鍵單擊 add to build path就ok了。


2.拋開這個框架類JdbcUtils.java來說,操作數(shù)據(jù)庫的一般性步驟如下:


    (1)連接數(shù)據(jù)庫,加載驅(qū)動: Class.forName(DRIVER); DRIVER = "com.mysql.jdbc.Driver";這本身就是反射?。?/span>


      (2) 利用用戶名和密碼及數(shù)據(jù)庫的名字連接,這一步才是真正的連接:


connection = DriverManager.getConnection(URL, USERNAME, PASSWORD); 


其中:String URL = "jdbc:mysql://localhost:3306/mydb";


     (3)編寫一個sql語句,其中的參數(shù)用?來代替,然后將參數(shù)寫到List里。


執(zhí)行:pstmt = connection.prepareStatement(sql); 然后將參數(shù)從list里取出來填充到pstmt里。


     (4)如果是增、刪、改執(zhí)行:result = pstmt.executeUpdate(); 其中的result是執(zhí)行完影響的數(shù)據(jù)庫里的行數(shù),也即幾條記錄。如果是查詢執(zhí)行:resultSet = pstmt.executeQuery(); 返回的類型是ResultSet類型。之后就是把resultSet 弄成Map或List<Map>傳遞出去,給查詢者看。


3.關(guān)于查詢操作,在得到resultSet后利用getMetaData得到表的結(jié)構(gòu)信息,如getColumnCount()得到有多少個列。String cols_name = metaData.getColumnName(i+1); 得到每個列的屬性名稱,如是id、username還是pswd.然后從Object cols_value = resultSet.getObject(cols_name);取出來,放到Map或List<Map>里。


4.關(guān)于查詢里利用的反射操作,步驟如下:


     (1) T resultObject = cls.newInstance(); 利用class文件的newInstance()方法創(chuàng)建一個實例。


     (2)在通過getColumnCount()得到有多少個列之后,進(jìn)入循環(huán),


                 String cols_name = metaData.getColumnName(i+1);

                 Object cols_value = resultSet.getObject(cols_name);


    讀取每一列的屬性名字和放的值。通過屬性的名字cols_name進(jìn)行反射:Field field = cls.getDeclaredField(cols_name);這樣就得到了Field 等于類里的成員變量,field.setAccessible(true); //打開javabean的訪問權(quán)限 在利用set方法將從數(shù)據(jù)庫中查出來的cols_value通過JavaBean 也即定義的UserInfo這個類的 set方法賦進(jìn)去。field.set(resultObject, cols_value);


5.一般意義上,要利用Java的反射需要以下步驟


     (1)加載Class對象,這個一般有兩種方式:Class cls1 = UserInfo.class  或


Class cls2 = Class.forName("domain.UserInfo") 后者是利用包名+類名的方法。


   (2)反射出來Class之后干啥事呢?一個類不外乎構(gòu)造函數(shù)、成員變量、成員函數(shù)。所以得到Class之后就可以干這三件事。


     A、關(guān)于構(gòu)造函數(shù),獲得Constructor 有四種方法: 


  Constructor getConstructor(Class[] params) 


Constructor[] getConstructors() 


Constructor getDeclaredConstructor(Class[] params) 


  Constructor[] getDeclaredConstructors()  


這四個函數(shù),如果不傳參數(shù)則是獲得所有的構(gòu)造函數(shù),得到的是一個集合。如果傳特定的參數(shù),則是尋找這個特定的構(gòu)造函數(shù),不帶Declared是獲得公共的public,帶了Declared是可以獲得私有構(gòu)造函數(shù)。 得到構(gòu)造函數(shù)后就可以利用反射創(chuàng)建實例了:


 Constructor con1[] = cls1.getDeclaredConstructors();

         con1[1].setAccessible(true);

    Object obj1 = con1[1].newInstance(new Object[]{"tom"}); 如果直接調(diào)用clcs.newInstance()則是用默認(rèn)的構(gòu)造函數(shù)創(chuàng)建實例。


      B、關(guān)于成員變量,同樣有四種方法:


public Field getDeclaredField(String name)  獲取任意指定名字的成員

public Field[] getDeclaredFields()          獲取所有的成員變量

public Field getField(String name)          獲取任意public成員變量

public Field[] getFields()                  獲取所有的public成員變量


本文封裝的JdbcUtils類就是利用這種方式操作類里的私有成員變量,記得要setAccessible打開開關(guān)。如下:


Field field = cls.getDeclaredField(cols_name);

field.setAccessible(true); //打開javabean的訪問權(quán)限

field.set(resultObject, cols_value);


    C、關(guān)于成員函數(shù),也有四種方法:


public Method[] getMethods()    獲取所有的共有方法的集合

public Method getMethod(String name,Class<?>... parameterTypes) 獲取指定公有方法 ,


參數(shù)1:方法名 參數(shù)2:參數(shù)類型集合  

public Method[] getDeclaredMethods()  獲取所有的方法

public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 獲取任意指定方法


下面是利用文中的UserInfo這個類寫的一個完成的反射例子,拿到setUsername(String username)方法,然后反射。再拿到getUsername()方法再反射,然后打印出結(jié)果:


Class clcs = UserInfo.class;

try {

Object obj = clcs.newInstance();

Method f = clcs.getDeclaredMethod("setUsername", String.class);

f.invoke(obj, "yan123");

Method f2 = clcs.getDeclaredMethod("getUsername", null);

Object name = f2.invoke(obj, null);

System.out.println("反射得到的名字 = "  +  name);



} catch (InstantiationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (NoSuchMethodException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (SecurityException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalArgumentException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InvocationTargetException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}


在反射方法的時候,Method f = clcs.getDeclaredMethod("setUsername", String.class); 原函數(shù)里的輸入?yún)?shù)是什么類型,就寫什么類型.class. 如原來的setXXX需要輸入?yún)?shù)String,反射的時候就寫String.class.


6. JavaBean是反射的一種,反射對構(gòu)造函數(shù)之類的沒任何要求,JavaBean要求這個類必須繼承Serializable即可串行化,另外構(gòu)造函數(shù)必須為public. 另外,就是JavaBean在得到某個field后可以直接調(diào)用set和get,而不必再反射得到method后再執(zhí)行。

--------------------- 



標(biāo)簽: 數(shù)據(jù)庫
分享:
評論:
你還沒有登錄,請先