java之jdbc學習——QueryRunner


jdbc是ORM框架的基礎,但將數據庫中的表映射到java對象,並進行增刪改查,並不是一件簡單的事情。

涉及到jdbc、注解和反射的一些基礎知識。

以下內容來自網友的分享,並做了一些增減,作為筆記記錄與此。

一、首先是數據表

假如數據庫中有一張表app_base_log,在java中建立它對應的類。

@Table(name = "app_base_log")
public class AppBaseLog implements Serializable {
    private static final long serialVersionUID = -5206763271093824440L;
    @Column(name = "dvid")
    private String dvid;
    @Column(name = "type")
    private String type;

    public AppBaseLog() {
    }

    public AppBaseLog(String dvid, String type) {
        this.dvid = dvid;
        this.type = type;
    }

    public String getDvid() {
        return dvid;
    }

    public void setDvid(String dvid) {
        this.dvid = dvid;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

這里的注解都是自定義的,並非來自hibernate和mybatis。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Table {
    String name();
}

/**
 * Created by wangbin10 on 2018/8/13.
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Id {
    String name();
    String type() default "int";
    int length() default 20;
    int increment() default 1;
}

/**
 * Created by wangbin10 on 2018/8/13.
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
    String name();
    String type() default "string";
    int length() default 20;
}

二、核心代碼

/**
 * Created by wangbin10 on 2018/8/13.
 */
public class SimpleORM<E> {
    @Autowired
    private QueryRunner queryRunner;
    /**
     * 添加一個對象
     */
    public int add(E element) throws SQLException {
        Class clazz = element.getClass();
        String tableName = getTableName(clazz);
        Field[] fields = clazz.getDeclaredFields();
        String sql = getInsertSql(tableName, fields.length);
        //通過對象和屬性列表獲取對應屬性的值
        Object[] params = getSqlParams(element, fields);
        int result = -1;
        result = queryRunner.update(sql, params);
        return result;
    }

    /**
     * 根據對象獲取sql語句的參數
     */
    private Object[] getSqlParams(E element, Field[] fields) {
        Object[] params = new Object[fields.length];
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);
            try {
                params[i] = fields[i].get(element);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return params;
    }

    /**
     * 獲取插入對象的sql語句
     */
    private String getInsertSql(String tableName, int length) {
        StringBuilder sql = new StringBuilder();
        sql.append("insert into ").append(tableName).append(" values(");
        for (int i = 0; i < length; i++) {
            sql.append("?,");
        }
        sql.deleteCharAt(sql.length() - 1);
        sql.append(")");
        return sql.toString();
    }

    /**
     * 根據值對象的注解獲取其對應的表名稱
     */
    private String getTableName(Class<E> clazz) {
        boolean existTableAnno = clazz.isAnnotationPresent(Table.class);
        if (!existTableAnno) {
            throw new RuntimeException(clazz + " 沒有Table注解.");
        }
        Table tableAnno = clazz.getAnnotation(Table.class);
        return tableAnno.name();
    }

    /**
     * 更新一個對象
     */
    public int update(E element) throws SQLException {
        Class clazz = element.getClass();
        Field[] fields = clazz.getDeclaredFields();
        Object[] params = new Object[fields.length];
        String sql = getUpdateSql(element, params);
        int result = queryRunner.update(sql, params);
        return result;
    }

    /**
     * 獲取更新記錄的sql語句並更新參數
     */
    private String getUpdateSql(E element, Object[] params) {
        Class clazz = element.getClass();
        String tableName = getTableName(clazz);
        Field[] fields = clazz.getDeclaredFields();
        StringBuilder updateSql = new StringBuilder();
        updateSql.append("update ").append(tableName).append(" set ");
        String idName = "";
        int index = 0; // 記錄參數的位置
        for (int i = 0; i < fields.length; i ++){
            fields[i].setAccessible(true);
            // 找到id對應的列名和值
            if (fields[i].isAnnotationPresent(Id.class)){
                idName = fields[0].getAnnotation(Id.class).name();
                try {
                    params[params.length-1] = fields[i].get(element);  // id作為update sql 的最后一個參數
                    if (params[params.length-1] == null)
                        throw new RuntimeException(element + "沒有Id屬性!");
                } catch (IllegalAccessException e) {
                    System.out.println(e.getMessage());
                    System.out.println("獲取" + element + "的屬性值失敗!");
                }
            }
            boolean isPresent = fields[i].isAnnotationPresent(Column.class);
            if (isPresent) {
                Column column = fields[i].getAnnotation(Column.class);
                String columnName = column.name();
                updateSql.append(" ").append(columnName).append( " = ? ,");
                try {
                    params[index++] = fields[i].get(element);  // 添加參數到數組,並更新下標
                } catch (IllegalAccessException e) {
                    System.out.println(e.getMessage());
                    System.out.println("獲取" + element + "的屬性值失敗!");
                }
            }
        }
        updateSql.deleteCharAt(updateSql.length()-1);
        updateSql.append("where ").append(idName).append(" = ?");
        return updateSql.toString();
    }

    /**
     * 根據id刪除一個對象
     */
    public int delete(String id, Class<E> clazz) throws SQLException {
        String deleteSql = getDeleteSql(clazz);
        int  result = queryRunner.update(deleteSql, id);
        return result;
    }

    private String getDeleteSql(Class<E> clazz) {
        String tableName = getTableName(clazz);
        String idName = getIdName(clazz);
        StringBuilder deleteSql = new StringBuilder();
        deleteSql.append("delete from ").append(tableName).append(" where ").append(idName).append(" = ?");
        return deleteSql.toString();
    }

    /**
     * 獲取id屬性對應的列名,根據值對象的字節碼
     */
    private String getIdName(Class<E> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        String idName = null;
        for (Field field : fields) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(Id.class)) {
                idName = field.getAnnotation(Id.class).name();
            }
        }
        if (idName == null) {
            throw new RuntimeException(clazz + "沒有指定@Id注解!");
        }
        return idName;
    }

    /**
     * 根據id查找一個對象
     */
    public E query(String id, Class<E> clazz) throws SQLException {
        String selectSql = getSelectSql(clazz);
        E result = queryRunner.query(selectSql, new BeanHandler<E>(clazz), id);
        return result;
    }

    private String getSelectSql(Class<E> clazz) {
        String tableName = getTableName(clazz);
        String idName = getIdName(clazz);
        StringBuilder selectSql = new StringBuilder();
        selectSql.append("select * from ").append(tableName).append(" where ").append(idName).append(" = ?");
        return selectSql.toString();
    }

    public List<E> queryToList(String sql, Class<E> clazz) throws SQLException {
        List<E>  result = queryRunner.query(sql, new BeanListHandler<E>(clazz));
        return result;
    }

    public Object[] queryToArray(String sql) throws SQLException {
        Object[]  result = queryRunner.query(sql, new ArrayHandler());
        return result;
    }

    /**
     * 查找該類對應的表中記錄的數目(對應記錄的數目)
     */
    public int count(Class<E> clazz) throws SQLException {
        String tableName = getTableName(clazz);
        String sql = "select count(*) from " + tableName;
        long  result = (Long) queryRunner.query(sql, new ScalarHandler());
        return (int) result;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM