1. 程式人生 > 實用技巧 >JDBC的批量新增-大資料處理-結果集的元資料-Class反射-JDBC查詢封裝

JDBC的批量新增-大資料處理-結果集的元資料-Class反射-JDBC查詢封裝

一、使用JDBC批量新增

​ 知識點複習:

​ JDBC的六大步驟 (匯入jar包, 載入驅動類,獲取連線物件, 獲取sql執行器、執行sql與並返回結果, 關閉資料庫連線)

​ 封裝了一個DBUtil 類, 通過讀取屬性檔案的方式獲取 基礎連線資訊。

​ 批量新增: 一次性可執行多個新增記錄 ,將多個sql語句在當前這次連線中執行完畢。

    // 設定部門集合
        List<Dept> list = new ArrayList<>();
        list.add(new Dept(60,"市場部","武漢市"));
        list.add(new Dept(70,"研發部","武漢市"));
        list.add(new Dept(80,"教學部","武漢市"));

          //通過DBUtil獲取資料庫連線
        Connection conn = DBUtil.getConn();
        String sql="insert into dept(deptno,dname,loc) values (?,?,?)";
          //獲取預編譯sql執行器
        PreparedStatement ps = conn.prepareStatement(sql);
        //批量設定該條sql語句的 引數
        for(Dept dept : list){
            //設定引數
            ps.setInt(1,dept.getDeptno());
            ps.setString(2,dept.getDname());
            ps.setString(3,dept.getLoc());
            // 將設定好的引數 先放入批量新增的容器中
            ps.addBatch();
            //  對於完整的sql語句 可以用有參的
           // ps.addBatch(sql);
        }
        // 執行sql語句  返回每一行sql語句影響的行數  ,
        int [] counts = ps.executeBatch();
        System.out.println("結果長度:"+ counts.length);
        System.out.println("結果:"+ Arrays.toString(counts));
        //關閉sql語句
        DBUtil.closeAll(conn,ps,null);

補充知識點: Java使用Excel批量匯入資料 到資料庫中

1、先將Excel通過Java 的 POI框架 讀取資料到記憶體中(List)

2、將List資料 批量新增到 資料庫中。

package com.j2008.jdbc2;


import com.j2008.jdbc.Dept;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import java.io.*;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

//import javax.validation.ConstraintViolation;
//import javax.validation.Validation;
//import javax.validation.Validator;
//import javax.validation.ValidatorFactory;
//import org.springframework.expression.EvaluationException;

/**
 * ClassName: ExcelUtil
 * Description:
 * date: 2020/11/23 9:33
 *
 * @author wuyafeng
 * @version 1.0   softeem.com
 */
public class ExcelUtil {
   // Logger logger = Logger.getLogger(this.getClass());

    private String description = "";// 如果校驗失敗,將會給出詳細提示資訊
    private Sheet sheet;// execel 物件
    private List<String> fieldList;//從xml讀取到的execel表格資訊
    private int rowIndex = 0;//當前操作行
    private Object objectBean;//每一行資料封裝
    private Cell cellStart;// 資料的開始單元格
    private Class clazz; //需要封裝的類
//    private Validator validator; //hibernate 的校驗器
    private String[] fieldVals ; //從execel讀到的某一行的資料
    private int fieldSize = 0;  //有效資料的列數
    private DateFormat format = new SimpleDateFormat("yyyy-MM-dd"); // 針對日期的預設轉換形式
    private Expression exp ;//EL 解析器
    private ExpressionParser parser;

    private DecimalFormat df = new DecimalFormat("#");

    public String getDescription() {
        return description;
    }

    public Object getObjectBean() {
        return objectBean;
    }

    public ExcelUtil(InputStream execelIS,String xmlFilename,
                     Class clazz,String suffix) throws Exception{
        // 開啟execel工作簿
        Workbook wb = null;
        try {
            if(suffix.equals(".xls")){
                wb = new HSSFWorkbook(execelIS);
            }else if(suffix.equals(".xlsx")){
                wb = new XSSFWorkbook(execelIS);
            }
            execelIS.close();
        } catch (IOException e) {
            throw new Exception("載入檔案失敗,請確保是否是Execel表格");
        }
        sheet = wb.getSheetAt(0);// 預設取第一個工作簿
        //讀配置檔案,獲取所有的屬性列描述
        fieldList = this.readFieldsFromXML(getAbsolutePath(xmlFilename));
        //個數
        fieldSize = fieldList.size();

        //找到有效資料的開始單元格
        cellStart = this.findStartCell();
        if(cellStart == null){
            throw new Exception(this.description);
        }

        //每次讀取一行execel資料,rowIndex每次增1
        rowIndex = cellStart.getRowIndex()+1;

        //需要封裝的物件類
        this.clazz = clazz;
        //初始化校驗器
//        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
//        validator = factory.getValidator();
//        //初始化EL解析器
        parser = new SpelExpressionParser();
        exp = parser.parseExpression("values");
    }

    //是否還有資料
    public boolean hasNext(){
        Row row = sheet.getRow(rowIndex++);
        if(row == null)
            return false;
        fieldVals = this.getRowValues(row, cellStart.getColumnIndex());
        if(Arrays.asList(fieldVals).indexOf("") != -1){
            for(String s :fieldVals)//如果每個欄位都是空的,則返回false 否則true
                if(!s.equals(""))
                    return true;
            return false;
        }
        return true;
    }
    //校驗
    public boolean validate(){
        try {
            objectBean = Class.forName(clazz.getName()).newInstance();
        } catch (Exception e) {
           // logger.error(e);
            e.printStackTrace();
        }


        try{
           exp.setValue(objectBean, fieldVals);// 給objectBean的屬性賦值

        }catch( Exception e){//由於所有的資料型別轉換都有objectBean裡面來處理,故可能有異常,需要進行相應的處理
            e.printStackTrace();
            return false;
        }

        return true;
    }

    private String[] getRowValues(Row row,int columnStartIndex){
        String[] values = new String[fieldSize];
        for(int j = columnStartIndex,t=0;t<fieldSize;j++,t++){
            Cell c = row.getCell(j);
            if(c==null){
                values[t] = "";
                continue;
            }
            switch(c.getCellType()){
                case Cell.CELL_TYPE_BLANK:
                    values[t] = "";
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    values[t] = String.valueOf(c.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_NUMERIC:

                    if (HSSFDateUtil.isCellDateFormatted(c)) {
                        values[t] = format.format(c.getDateCellValue());
                    } else if(c.getCellStyle().getDataFormat() == 58) {
                        // 處理自定義日期格式:m月d日(通過判斷單元格的格式id解決,id的值是58)
                        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd");
                        double value = c.getNumericCellValue();
                        Date date = org.apache.poi.ss.usermodel.DateUtil
                                .getJavaDate(value);

                        values[t] = sdf.format(date);
                    }
                    else {
                        values[t] = new DecimalFormat("#").format(c.getNumericCellValue());
                    }
                    break;
                case Cell.CELL_TYPE_STRING:
                    values[t] = String.valueOf(c.getStringCellValue());
                    break;

                default:
                    values[t] = "";
                    break;
            }
        }
        return values;
    }
    // 根據某一個單元格,得到更人性化的顯示,例如“A4”
    private String getCellRef(Cell cell) {
        return CellReference.convertNumToColString(cell.getColumnIndex()) + (cell.getRowIndex() + 1);
    }
    private  String getAbsolutePath(String file) throws Exception {
        try {
            file = this.getClass().getClassLoader().getResource(file).getFile();

        } catch (NullPointerException e) {
            throw new Exception("檔案不存在");
        }
        try {
            // 解決當出現中文路徑時不能解析的bug
            file = URLDecoder.decode(file, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new Exception( "解碼失敗");
        }
        return file;
    }
    private List<String> readFieldsFromXML(String xmlFilename)throws Exception{
        SAXReader reader = new SAXReader();
        Document document = null;

        try {
            document = reader.read(new File(xmlFilename));// 載入配置檔案
        } catch (DocumentException e) {
            e.printStackTrace();
            this.description = "IO 異常,讀取配置檔案失敗";
            throw new Exception("IO 異常,讀取配置檔案失敗");
        }

        Element root = document.getRootElement();
        List<String> fields = new ArrayList<String>();
        for (Iterator iter = root.elementIterator("field"); iter.hasNext();) {
            Element field = (Element) iter.next();
            fields.add(field.getTextTrim());
        }

        return fields;
    }
    /**
     * 從execel表中找到資料開始的單元格
     * @return
     */
    private  Cell findStartCell(){
        String firstFieldDesc = this.fieldList.get(0);
        int endRow = sheet.getLastRowNum()>100?100:sheet.getLastRowNum();
        for(int i = 0;i<=endRow;i++){
            Row r = sheet.getRow(i);
            if (r == null)
                continue;
            for(int j = 0;j < r.getLastCellNum();j++){
                Cell c = r.getCell(j);
                if( c == null)
                    continue;
                if(c.getCellType() == Cell.CELL_TYPE_STRING){
                    if(c.getStringCellValue().trim().equals(firstFieldDesc)){//找到第一個符合要求的欄位,接下來判斷它相鄰的欄位是否都符合要求
                        if(fieldList.size()>r.getLastCellNum()-j){
                            this.description = "execel表格與所給配置描述不符,請下載模板檔案";
                            return null;
                        }
                        for(int k=j+1,t=1;k<=j+fieldList.size()-1;k++,t++){
                            Cell c2 = r.getCell(k);
                            if(c2 == null){
                                this.description = "請確保單元格"+this.getCellRef(c2)+"內容是\""+fieldList.get(t)+"\"";
                                return null;
                            }
                            if(c2.getCellType() == Cell.CELL_TYPE_STRING){
                                if(c2.getStringCellValue().contains(fieldList.get(t)))
                                    continue;
                                else{
                                    this.description = "請確保單元格"+this.getCellRef(c2)+"內容是\""+fieldList.get(t)+"\"";
                                    return null;
                                }
                            }

                        }
                        return c;
                    }else
                        continue;
                }else
                    continue;
            }
        }
        this.description = "找不到\""+fieldList.get(0)+"\"這一列";
        return null;
    }

    public int getRowIndex() {
        return rowIndex;
    }

    public DateFormat getFormat() {
        return format;
    }


    public String createExcelIncludeFailReason(InputStream execelIS,String path,String newExcelName, HashMap<Integer,String> errHash) {
        FileOutputStream file;
        try {
            file = new FileOutputStream(path+"/"+newExcelName);
            Workbook workbook=this.getWorkbook(execelIS);
            Sheet s=workbook.getSheetAt(0);

            //int endRow = sheet.getLastRowNum()>100?100:sheet.getLastRowNum();
            int endRow = sheet.getLastRowNum();
            for(int i=1;i<=endRow;i++){
                if(errHash.get(i)!=null){
                    Row rowkk = s.getRow(i);
                    Cell error_cell = rowkk.createCell(fieldList.size());
                    error_cell.setCellValue(errHash.get(i));
                }
            }
            workbook.write(file);
            file.close();
        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        } catch (Exception e) {

            e.printStackTrace();
        }

        return newExcelName;
    }


    public String getFile(InputStream execelIS,String path,String appPath, List<Integer> listF, boolean b) {
        FileOutputStream file;
        try {
            file = new FileOutputStream(path+"/"+appPath);
            Workbook workbook=this.getWorkbook(execelIS);
            Sheet s=workbook.getSheetAt(0);
            Row row=null;
            //int endRow = sheet.getLastRowNum()>100?100:sheet.getLastRowNum();
            int endRow = sheet.getLastRowNum();
            for(int i=1;i<=endRow;i++){

                Row rowkk = s.getRow(i);
                Cell info_cell = rowkk.createCell(fieldList.size());
                info_cell.setCellValue("sss");

                //刪除錯誤行
                if(b&& listF.contains(i)){
                    row=s.getRow(i);
                    if(row!=null)s.removeRow(row);
                }
                //刪除正確行
                if(!b && !listF.contains(i)){
                    row=s.getRow(i);
                    if(row!=null)s.removeRow(row);
                }
            }
            workbook.write(file);
            file.close();
        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return appPath;
    }
    public  Workbook  getWorkbook(InputStream execelIS) throws Exception{
        Workbook wb = null;
        try {
            wb = new HSSFWorkbook(execelIS);
        } catch (IOException e) {
            throw new Exception("載入檔案失敗,請確保是否是Execel表格");
        }
        return wb;
    }


    /**
     * 返回List集合
     * @param filePath
     * @param xmlName
     * @return
     * @throws Exception
     */
    public static List<Dept> getListByExcel(String filePath,String xmlName ) throws Exception {
        InputStream is = new FileInputStream(filePath);
        ExcelUtil eu = new ExcelUtil(is, xmlName, Dept.class,".xls");
        Dept cp = null;
        List<Dept> list = new ArrayList<>();
        while (eu.hasNext()) {
            if (eu.validate()) {
               // System.out.println( eu.getObjectBean());
                cp = (Dept) eu.getObjectBean();
              //  System.out.println(cp.getDeptno()+"/"+cp.getDname()+ "/"+cp.getLoc() );
                list.add(cp);
            }
        }
        return list;

    }

    

    /**
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {

        /**
         *  使用Excel工具的前提
         *   1、定義一個實體類 , 並提供基本的get set方法 和 setValues方法
         *   2、提供一個 表頭的 xml檔案。  表頭的名字和  xml中的   <field>部門編號</field>  一致
         *   3、 源資料: D:/dept.xls
         */

       List<Dept>  list =   getListByExcel("D:/dept.xls","importTitle.xml");
         for(Dept d : list){
             System.out.println(d);
         }
    }
}

二、JDBC處理大資料型別(Blob ,Text)

​ 將資料庫中儲存 類似圖片,視訊,音訊,小說等這些大資料型別格式是,JDBC如何操作

分兩種情況: 位元組資料和字元資料

1、位元組資料:

​ 原理: 存資料(新增記錄):使用位元組流先 讀取到 記憶體中, 然後在儲存資料中,

​ 取資料(根據id查詢該結果記錄): 先通過jdbc 從結果集中獲取輸入位元組流,將位元組流寫出到磁碟中

新增資料:

  /**
     *  新增一個大資料型別
     * @throws Exception
     */
    public static void addImg() throws Exception {
        //獲取連線
       Connection conn =  DBUtil.getConn();
       //獲取預編譯sql執行器
        String sql ="insert into mytest2 values(?,?,?,?,?)";
        PreparedStatement ps = conn.prepareStatement(sql);
        // 設定引數
        ps.setInt(1,1002);
        ps.setString(2,"李四");
        ps.setString(3,"男");
        ps.setString(4,"自我介紹說明");
        // 讀取圖片的源路徑
        File file = new File("e:/12.jpg");
        FileInputStream fis = new FileInputStream(file);
        // 需要一個輸入流
       // ps.setBlob(5,fis);
        ps.setBinaryStream(5,fis);
        //執行sql語句
       int count =   ps.executeUpdate();
       if(count>0){
           System.out.println("新增成功");
       }
       //關閉流
        DBUtil.closeAll(conn,ps,null);

    }

查詢資料:

 /**
     *  根據id 獲取 圖片資訊
     * @param id
     */
    public static String findById(int id) throws Exception {
            // 獲取資料庫連線
        Connection conn = DBUtil.getConn();
        //獲取預編譯sql執行器
        String sql = "select * from mytest2 where id = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1,id);
        ResultSet rs = ps.executeQuery();
        if(rs.next()){
            //獲取記錄
           String username =  rs.getString(2);
           //獲取位元組型別 blob
           Blob image = rs.getBlob("image");
           //獲取位元組流
           InputStream is =  image.getBinaryStream();
            FileOutputStream fos = new FileOutputStream("d:/my.jpg");
            // 檔案讀寫
            byte [] b = new byte[1024];
            int len=0;
            while((len = is.read(b))!=-1){
                fos.write(b,0,len);
            }
            System.out.println("檔案儲存成功");
            fos.close();
            is.close();

            // 獲取字元流 寫出到檔案中  text欄位可直接通過String對映,也可以通過字元流
            Reader reader = rs.getCharacterStream("introduce");
            // 字元輸出流 寫出
            Writer writer = new FileWriter("d:/introduce.txt");
            char [] c = new char[1024];
            int len2 = 0;
            while( (len2 = reader.read(c)) !=-1){
                writer.write(c, 0 ,len2);
            }
            writer.close();
            reader.close();

            return username;

        }
        DBUtil.closeAll(conn,ps,rs);

        return null;

    }

三、JDBC元資料

​ 資料庫的元資料表示資料庫資訊 和 結果集資訊的 基礎資訊

1、 資料庫元資料資訊: DataBaseMetaData

​ 方法說明:

         //獲取資料庫連線
        Connection conn = DBUtil.getConn();
        DatabaseMetaData dbMetaData =  conn.getMetaData();
        System.out.println("資料庫產品名稱:"+ dbMetaData.getDatabaseProductName());
        System.out.println("資料庫的主要版本"+dbMetaData.getDatabaseMajorVersion());
        System.out.println("資料庫產品資訊的版本"+dbMetaData.getDatabaseProductVersion());

        System.out.println("資料庫的url:"+dbMetaData.getURL());
        System.out.println("驅動類:"+dbMetaData.getDriverName());
        System.out.println("使用者名稱:"+dbMetaData.getUserName());

2、 結果集的元資料 ResultSetMetaData

用於獲取結果集的基礎資訊(處理資料項以外的資訊),例如欄位名稱,欄位個數,欄位的資料型別 ,欄位值

用途: 可以通過欄位資訊 與Java實體類做對映關係 ,實現簡易的ORM(Object Relation Mapping)框架

API :

getColumnCount

getColumnCount() : 獲取欄位的列個數

getColumnLabel(i) : 獲取指定列的欄位名

getColumnType(i):獲取指定列的 類型別 : 常用類:

getColumnName() : 獲取欄位名 與getColumnLabel一樣

1:char; 3:BigDecimal 4:int ;12 varchar 91 :Date

四、反射基礎知識

1、為什麼需要使用反射

​ 由於之前建立物件的過程 ,是已知這個類,然後對類進行編譯,編譯通過之後才可以建立物件, 現在可能出現 “未知的類” 只有“包名+類名” ,在執行期間才知道 該類是否存在,並動態建立該類的物件。 這時 建立物件的過程 可以通過反射的方式 完成。

​ 反射機制的定義: 對於任意一個類,都可以在執行期間,動態的建立該類的物件,能知曉該物件的屬性和方法,並動態呼叫屬性 和方法 ,這個過程就是Java的反射機制

​ 對於任意類 都存在一個該類的Class型別 ,如何獲取類的Classs型別

方式一: Class cls = Class.forName("類的全類名")

方式二: Class cls = 類名.class;

方式三: Class cls = 類的物件名.getClass()

常用API

Construct:

​ cls.getConstructor(int.class , String.class); 根據引數型別和個數 獲取cls 對應的 構造器物件

Field : 屬性對應的型別

​ getDeclareFields () : 獲取所有宣告的屬性 (包括 任何修飾符,不包括private修飾)

​ getFields(): 獲取所有宣告的public修飾的屬性

getDeclareFiled(String name): 根據屬性名獲取屬性物件

getField(String name):根據屬性名獲取屬性物件 (必須是共有的 )

Method : 方法對應的型別

​ getDeclaredMethods() : 返回當前類的自己宣告的方法

​ getMethods() :返回所有的方法(包括父類的)

​ invoke(obj,引數值) :呼叫該方法

​ getMethod(“方法名” ,引數值):根據方法名返回Method

            //獲取所有的方法   返回當前類的自己宣告的方法
            Method [] methods =  cls.getDeclaredMethods();
            System.out.println("當前類自己的方法========");
            for(Method  m : methods){
                //遍歷每一個方法
                System.out.println(m.getName()+"------"+ m.getReturnType());
            }

            Method [] methods2 = cls.getMethods();
            System.out.println("它的所有方法=============");
            for(Method m : methods2){
                System.out.println(m.getName()+"---"+m);
            }

            // 呼叫屬性 和 方法
            // 獲取指定方法的方法
            Method m = cls.getMethod("sayHello", String.class);
            //呼叫方法 (引數1 : 方法所屬的物件oibj  ,引數n : 方法的引數值)
            // retObj :方法呼叫的返回值
            Object retObj =  m.invoke(myObj,"商騰輝");
            System.out.println("方法返回值:"+retObj);


使用反射完成物件屬性的拷貝功能

 /**
     * 物件的屬性值拷貝
     * @param fromObj
     * @param toObj
     */
    public static void copy(Object fromObj ,Object toObj) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //獲取這個物件的Class型別
        Class fromCls = fromObj.getClass();
        Class toCls = toObj.getClass();

        // 獲取源物件的所有屬性名
       Field[] fields = fromCls.getDeclaredFields();
       for(Field f : fields){
           //構建  getXxx的方法
           String methodName = "get"+ f.getName().substring(0,1).toUpperCase() +
                            f.getName().substring(1);
           //獲取getXxx方法
           Method getMethod =  fromCls.getMethod(methodName,null);
           // 1 呼叫源物件的get方法,獲取返回值, (如何獲取get方法呢   id-》getId )
           Object value = getMethod.invoke(fromObj ,null);
           // 2 呼叫目標物件的set方法,設定值 ( set方法的引數型別 就是get方法的返回值型別,引數值就是get方法的返回值)
            String methodName2 ="set"+ f.getName().substring(0,1).toUpperCase() +
                    f.getName().substring(1);
           Method setMethod =   toCls.getMethod(methodName2,getMethod.getReturnType());
           //呼叫set方法
           setMethod.invoke(toObj ,value);
           System.out.println("屬性賦值成功");
       }



      }

     Student stu1 = new Student(1001,"admin",22,"男");
        //目標物件
        Student stu2 = new Student();
        //複製物件的屬性
        copy(stu1,stu2);
        System.out.println(stu1);
        System.out.println(stu2);

五、JDBC的新增,查詢封裝 (反射知識點)

​ 目前我們只對JDBC的 獲取連線,關閉進行封裝,對於 資料庫表的操作 新增,刪除修改,查詢,根據id查詢 ,都需要單獨寫,這樣太麻煩了, 需要將公有的程式碼 簡化。

​ 1、對新增,刪除,修改方法寫成一個方法

/**
     * 對於 新增,刪除,修改方法    不同點在於  sql語句不同
     *  引數不同
     * @param sql  sql語句   insert into dept values(?,?,?)
     * @param objs 任意個數任意型別的引數  與sql的?一一對應
     * @return
     */
    public static  int executeUpdate(String sql ,Object ... objs){
        // 獲取連線
        Connection conn=null;
        PreparedStatement ps=null;
        // 獲取預編譯sql執行器
        try {
            conn = DBUtil.getConn();
            ps = conn.prepareStatement(sql);
            //設定引數
            if(objs!=null){
                for(int i=0;i<objs.length;i++){
                    // 引數從1開始,陣列objs的下標從0開始
                    ps.setObject(i+1 ,objs[i]);
                }
            }
            //執行sql語句
           int count = ps.executeUpdate();
            return count;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //關閉連線
            DBUtil.closeAll(conn,ps,null);
        }
        return 0;
    }

查詢

  /**
     * 查詢所有的公共方法, 可以自動將結果集對映到 實體類上
     * @param sql  sql語句
     * @param cls  實體類的型別
     * @param <T>  實體類的泛型
     * @return
     */
    public static<T> List<T> listAll(String sql ,Class cls ){
        // 儲存結果集的集合list
        List<T> list = new ArrayList<T>();
        Connection conn=null;
        PreparedStatement ps = null;
        ResultSet rs=null;
        try {
            //獲取連線
            conn = DBUtil.getConn();
            ps = conn.prepareStatement(sql);
            rs  = ps.executeQuery();
            while(rs.next()){
                // 建立這個型別的物件
                Object obj = cls.newInstance();
                // 獲取這個類的所有欄位個數  獲取每一行的元資料
                ResultSetMetaData rsmd = rs.getMetaData();
                int clsCount =rsmd.getColumnCount();
                for(int i=1;i<=clsCount;i++){
                    String columnName = rsmd.getColumnLabel(i);
                    //構建set方法
                    String setMethod =  "set"+columnName.substring(0,1).toUpperCase() + columnName.substring(1);
                   // 呼叫get方法 獲取返回值型別
                    String getMethod = "get"+columnName.substring(0,1).toUpperCase() + columnName.substring(1);
                    Method m1 = cls.getMethod(getMethod,null);

                    //呼叫方法  方法的引數型別  是 get方法的返回值型別
                    Method m = cls.getMethod(setMethod, m1.getReturnType());
                    // 呼叫set方法
                    m.invoke(obj,rs.getObject(columnName));

                }
                // 將obj放入 list中
                list.add((T)obj);

            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }  catch (NoSuchMethodException e) {
            e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            DBUtil.closeAll(conn,ps,rs);
        }

        return list;
    }
/**
     * 根據id查詢一行記錄
     * @param sql
     * @param cls
     * @param <T>
     * @return
     */
    public static<T> T getById(String sql ,Class cls){
       List<T> list =  listAll(sql,cls)  ;
       //查詢一個集合,取第一行記錄
       return list.size()>0 ? list.get(0) : null;
    }