六:Dao

言字旁發表於2020-12-20

Dao

一:升級前的Dao

(1):提供運算元據表的BaseDao

package cn.hgk.dao;
/**
 * 封裝了針對於資料表的通用的操作
 */
import cn.hgk.util.JDBCUtils;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;

public abstract class BaseDao {
    
    //通用的增刪改操作:version2.0(考慮事務)
    public int update2(Connection conn, String sql, Object... args) {//sql中佔位符的個數與可變形參的個數相同。可變形參看成陣列即可
        PreparedStatement ps = null;
        try {
            //1.預編譯sql語句,返回prepareStatement的例項
            ps = conn.prepareStatement(sql);
            //2.填充佔位符
            for (int i = 0; i < args.length; i++) {//注意索引一定要從1開始!!!
                ps.setObject(i + 1, args[i]);
            }
            //3.執行
            return ps.executeUpdate();//executeUpdate():影響了幾條記錄
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null && ps != null) {
                //4.資源的關閉
                JDBCUtils.closeResource(null, ps);
            }
        }
        return 0;
    }

    //通用的查詢操作,用於返回資料表中的一條記錄(考慮事務之後)
    public <T> Object getInstance(Connection conn, Class<T> clazz, String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            //填充佔位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            rs = ps.executeQuery();
            //獲取結果集的後設資料(型別,名字):ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
            //通過ResultSetMetaData獲取結果集中的列數
            int columnCount = rsmd.getColumnCount();
            if (rs.next()) {
                T t = clazz.newInstance();
                //處理結果集一行資料中的每一個列
                for (int i = 0; i < columnCount; i++) {
                    //獲取列值
                    Object value = rs.getObject(i + 1);
                    //獲取列的別名(重點):不管有沒有別名,都推薦使用這個getColumnLabel()方法。
                    String columnLaber = rsmd.getColumnLabel(i + 1);
                    //通過反射,給t物件指定的某個屬性,賦值為value
                    Field field = clazz.getDeclaredField(columnLaber);
                    field.setAccessible(true);
                    field.set(t, value);
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(null, ps, rs);
        }
        return null;
    }

    //通用的查詢操作,有多個返回物件.version 2.0(考慮了事務之後)
    public <T> ArrayList<T> getArrayListInstance(Connection conn, Class<T> clazz, String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            //填充佔位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            rs = ps.executeQuery();
            //獲取結果集的後設資料(型別,名字):ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
            //通過ResultSetMetaData獲取結果集中的列數
            int columnCount = rsmd.getColumnCount();
            //建立儲存物件的集合
            ArrayList<T> clazzes = new ArrayList<T>();
            while (rs.next()) {
                T t = clazz.newInstance();
                //處理結果集一行資料中的每一個列
                for (int i = 0; i < columnCount; i++) {
                    //獲取列值
                    Object value = rs.getObject(i + 1);
                    //獲取列的別名(重點):不管有沒有別名,都推薦使用這個getColumnLabel()方法。
                    String columnLaber = rsmd.getColumnLabel(i + 1);
                    //通過反射,給t物件指定的某個屬性,賦值為value
                    Field field = clazz.getDeclaredField(columnLaber);
                    field.setAccessible(true);
                    field.set(t, value);
                }
                clazzes.add(t);
            }
            return clazzes;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(null, ps, rs);
        }
        return null;
    }
    
    //用於查詢特殊值的通用方法
    public <E> E getValue(Connection conn, String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            rs = ps.executeQuery();
            if (rs.next()) {
                return (E) rs.getObject(1);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            JDBCUtils.closeResource(null, ps, rs);
        }
        return null;
    }
}

(2):規_範針對於具體表的常用操作的介面_

/**
 * 此介面用於規範針對於customer表的常用操作
 */
public interface CustomerDAO {
    /**
     * 將cust物件新增到資料庫中
     * @param conn
     * @param cust
     */
    void insert(Connection conn, Customer cust);
    /**
     * 針對指定的ID,刪除表中的一條記錄
     * @param conn
     * @param id
     */
    void deleteById(Connection conn,int id);
    /**
     * 針對記憶體中的cust物件,去修改資料表中指定的記錄
     * @param conn
     * @param cust
     */
    void update(Connection conn,Customer cust);
    /**
     * 針對指定的ID查詢得到對應的Customer物件
     * @param conn
     * @param id
     */
    void getCustomerById(Connection conn,int id);
    /**
     * 查詢表中的所有記錄構成的集合
     * @param conn
     * @return
     */
    List<Customer> getAll(Connection conn);
    /**
     * 返回資料表中的資料的條目數
     * @param conn
     * @return
     */
    Long getCount(Connection conn);

    /**
     * 返回資料表中最大的生日
     * @param conn
     * @return
     */
    Date getMaxBirth(Connection conn);
}

(3):規_範針對於具體表的常用操作的介面的實現類_

public class CustomerDAOimpl extends BaseDao implements CustomerDAO {
    @Override
    public void insert(Connection conn, Customer cust) {
        String sql = "insert into customers(name,email,birth) values(?,?,?)";
        update(conn,sql,cust.getName(),cust.getEmail(),cust.getBirth());
    }

    @Override
    public void deleteById(Connection conn, int id) {
        String sql = "delete from customers where id = ?";
        update(conn,sql,id);
    }

    @Override
    public void update(Connection conn, Customer cust) {
        String sql = "update customers set name = ?,email = ?,birth = ?,where id = ?";
        update(conn,sql,cust.getName(),cust.getName(),cust.getEmail(),cust.getId());
    }

    @Override
    public Customer getCustomerById(Connection conn, int id) {
        String sql = "select id,name,birth from customers where id = ?";
        Customer customer = (Customer) getInstance(conn, Customer.class, sql, id);
        return customer;
    }

    @Override
    public List<Customer> getAll(Connection conn) {
        String sql = "select id,name,email,birth from customers";
        ArrayList<Customer> list = getArrayListInstance(conn, Customer.class, sql);
        return list;
    }

    @Override
    public Long getCount(Connection conn) {
        String sql = "select count(*) form customers";
        return getValue(conn,sql);
    }

    @Override
    public Date getMaxBirth(Connection conn) {
        String sql = "select max(birth) from customers";
        return getValue(conn,sql);
    }
}

二:升級後的Dao

(1):提供運算元據表的BaseDao

public abstract class BaseDao<T> {
    private Class<T> clazz = null;
    {
        //獲取當前DAO的子類繼承父類的泛型
        Type genericSuperclass = this.getClass().getGenericSuperclass();
        ParameterizedType paramType = (ParameterizedType) genericSuperclass;
        Type[] typeArguments = paramType.getActualTypeArguments();//讀取了父類的泛型引數
        clazz = (Class<T>) typeArguments[0];//泛型的第一個引數
    }
    //通用的增刪改操作:version2.0(考慮事務)
    public int update(Connection conn, String sql, Object... args) {//sql中佔位符的個數與可變形參的個數相同。可變形參看成陣列即可
        PreparedStatement ps = null;
        try {
            //1.預編譯sql語句,返回prepareStatement的例項
            ps = conn.prepareStatement(sql);
            //2.填充佔位符
            for (int i = 0; i < args.length; i++) {//注意索引一定要從1開始!!!
                ps.setObject(i + 1, args[i]);
            }
            //3.執行
            return ps.executeUpdate();//executeUpdate():影響了幾條記錄
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null && ps != null) {
                //4.資源的關閉
                JDBCUtils.closeResource(null, ps);
            }
        }
        return 0;
    }

    //通用的查詢操作,用於返回資料表中的一條記錄(考慮事務之後)
    public  T  getInstance(Connection conn, String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            //填充佔位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            rs = ps.executeQuery();
            //獲取結果集的後設資料(型別,名字):ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
            //通過ResultSetMetaData獲取結果集中的列數
            int columnCount = rsmd.getColumnCount();
            if (rs.next()) {
                T t = clazz.newInstance();
                //處理結果集一行資料中的每一個列
                for (int i = 0; i < columnCount; i++) {
                    //獲取列值
                    Object value = rs.getObject(i + 1);
                    //獲取列的別名(重點):不管有沒有別名,都推薦使用這個getColumnLabel()方法。
                    String columnLaber = rsmd.getColumnLabel(i + 1);
                    //通過反射,給t物件指定的某個屬性,賦值為value
                    Field field = clazz.getDeclaredField(columnLaber);
                    field.setAccessible(true);
                    field.set(t, value);
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(null, ps, rs);
        }
        return null;
    }

    //通用的查詢操作,有多個返回物件.version 2.0(考慮了事務之後)
    public ArrayList<T> getArrayListInstance(Connection conn,String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            //填充佔位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            rs = ps.executeQuery();
            //獲取結果集的後設資料(型別,名字):ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
            //通過ResultSetMetaData獲取結果集中的列數
            int columnCount = rsmd.getColumnCount();
            //建立儲存物件的集合
            ArrayList<T> clazzes = new ArrayList<T>();
            while (rs.next()) {
                T t = clazz.newInstance();
                //處理結果集一行資料中的每一個列
                for (int i = 0; i < columnCount; i++) {
                    //獲取列值
                    Object value = rs.getObject(i + 1);
                    //獲取列的別名(重點):不管有沒有別名,都推薦使用這個getColumnLabel()方法。
                    String columnLaber = rsmd.getColumnLabel(i + 1);
                    //通過反射,給t物件指定的某個屬性,賦值為value
                    Field field = clazz.getDeclaredField(columnLaber);
                    field.setAccessible(true);
                    field.set(t, value);
                }
                clazzes.add(t);
            }
            return clazzes;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(null, ps, rs);
        }
        return null;
    }

    //用於查詢特殊值的通用方法
    public <E> E getValue(Connection conn, String sql, Object... args) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            rs = ps.executeQuery();
            if (rs.next()) {
                return (E) rs.getObject(1);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            JDBCUtils.closeResource(null, ps, rs);
        }
        return null;
    }
}

(2):規_範針對於具體表的常用操作的介面_

//介面沒有變
/**
 * 此介面用於規範針對於customer表的常用操作
 */
public interface CustomerDAO {
    /**
     * 將cust物件新增到資料庫中
     * @param conn
     * @param cust
     */
    void insert(Connection conn, Customer cust);
    /**
     * 針對指定的ID,刪除表中的一條記錄
     * @param conn
     * @param id
     */
    void deleteById(Connection conn,int id);
    /**
     * 針對記憶體中的cust物件,去修改資料表中指定的記錄
     * @param conn
     * @param cust
     */
    void update(Connection conn,Customer cust);
    /**
     * 針對指定的ID查詢得到對應的Customer物件
     * @param conn
     * @param id
     */
    Customer getCustomerById(Connection conn,int id);
    /**
     * 查詢表中的所有記錄構成的集合
     * @param conn
     * @return
     */
    List<Customer> getAll(Connection conn);
    /**
     * 返回資料表中的資料的條目數
     * @param conn
     * @return
     */
    Long getCount(Connection conn);

    /**
     * 返回資料表中最大的生日
     * @param conn
     * @return
     */
    Date getMaxBirth(Connection conn);
}

(3):規_範針對於具體表的常用操作的介面的實現類_

public class CustomerDAOimpl extends BaseDao<Customer> implements CustomerDAO {

    @Override
    public void insert(Connection conn, Customer cust) {
        String sql = "insert into customers(name,email,birth) values(?,?,?)";
        update(conn,sql,cust.getName(),cust.getEmail(),cust.getBirth());
    }

    @Override
    public void deleteById(Connection conn, int id) {
        String sql = "delete from customers where id = ?";
        update(conn,sql,id);
    }

    @Override
    public void update(Connection conn, Customer cust) {
        String sql = "update customers set name = ?,email = ?,birth = ?,where id = ?";
        update(conn,sql,cust.getName(),cust.getName(),cust.getEmail(),cust.getId());
    }

    @Override
    public Customer getCustomerById(Connection conn, int id) {
        String sql = "select id,name,birth from customers where id = ?";
        Customer customer = (Customer) getInstance(conn,sql, id);
        return customer;
    }

    @Override
    public List<Customer> getAll(Connection conn) {
        String sql = "select id,name,email,birth from customers";
        ArrayList<Customer> list = getArrayListInstance(conn,sql);
        return list;
    }

    @Override
    public Long getCount(Connection conn) {
        String sql = "select count(*) form customers";
        return getValue(conn,sql);
    }

    @Override
    public Date getMaxBirth(Connection conn) {
        String sql = "select max(birth) from customers";
        return getValue(conn,sql);
    }
}

相關文章