1. 程式人生 > >基於反射+註解+迭代+泛型實現的一對多查詢方法

基於反射+註解+迭代+泛型實現的一對多查詢方法

主要是加入兩個新註解

一個Entity註解,加在類的實體屬性上

 

/**
 * 實體物件屬性的註解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
    //表名註解
    String table();
    //對應的非實體物件屬性名
    String field();
    //實體類地址
    String address();
    //名稱
    String name();
}

另一個為類似於外來鍵的註解,只不過是外來鍵所對應的屬性

 

 

/**
 * 外來鍵註解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Key {
    //對應Entity註解的表名
    String farther();
}

構造實體類如下

 

 

@Table(name = "first_type")
public class FirstType implements Serializable{
    /**
     * 書本一級型別id
     */
    @Id(name = "id")
    @Column(name = "id")
    private String id;
    /**
     * 書本一級型別名稱
     */
    @Column(name = "name")
    private String  name;
    /**
     *刪除標記,0正常,1刪除
     */
    @Column(name = "del_flag")
    private Integer deleteFlag;


    @Entity(table = "sub_type",field = "id",address = "cn.keduox.entity.SubType",name = "subTypeList")
    List<SubType> subTypeList=new ArrayList<>();

    public Integer getDeleteFlag() {
        return deleteFlag;
    }

    public void setDeleteFlag(Integer deleteFlag) {
        this.deleteFlag = deleteFlag;
    }


    public FirstType(String id, String name, List<SubType> subTypeList) {
        this.id = id;
        this.name = name;
        this.subTypeList = subTypeList;
    }

    public List<SubType> getSubTypeList() {
        return subTypeList;
    }

    public void setSubTypeList(List<SubType> subTypeList) {
        this.subTypeList = subTypeList;
    }

    public FirstType() {
    }

    public FirstType(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
@Table(name = "sub_type")
public class SubType implements Serializable{
    /**
     * id
     */
    @Id(name = "id")
    @Column(name = "id")
    private String id;
    /**
     * 名稱
     */
    @Column(name = "name")
    private String name;
    /**
     * 所屬父型別id
     */
    @Column(name = "first_type_id")
    @Key(farther = "sub_type")
    private String firstTypeId;
    /**
     * 所屬父型別
     */
    private FirstType firstType;
    /**
     * 包含的子型別
     */
    @Entity(table = "second_type",field = "id",address = "cn.keduox.entity.SecondType",name = "secondTypeList")
    List<SecondType> secondTypeList=new ArrayList<>();

    public Integer getDeleteFlag() {
        return deleteFlag;
    }

    public void setDeleteFlag(Integer deleteFlag) {
        this.deleteFlag = deleteFlag;
    }

    /**
     *刪除標記,0正常,1刪除

     */
    @Column(name = "del_flag")
    private Integer deleteFlag;

    public SubType(String id, String name, String firstTypeId) {
        this.id = id;
        this.name = name;
        this.firstTypeId = firstTypeId;
    }

    public SubType() {
    }

    public SubType(String id, String name, String firstTypeId, FirstType firstType, List<SecondType> secondTypeList) {
        this.id = id;
        this.name = name;
        this.firstTypeId = firstTypeId;
        this.firstType = firstType;
        this.secondTypeList = secondTypeList;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getFirstTypeId() {
        return firstTypeId;
    }

    public void setFirstTypeId(String firstTypeId) {
        this.firstTypeId = firstTypeId;
    }

    public FirstType getFirstType() {
        return firstType;
    }

    public void setFirstType(FirstType firstType) {
        this.firstType = firstType;
    }

    public List<SecondType> getSecondTypeList() {
        return secondTypeList;
    }

    public void setSecondTypeList(List<SecondType> secondTypeList) {
        this.secondTypeList = secondTypeList;
    }
}

BaseDaoImpl的查詢方法如下:

 

 

 /**
     * 查詢方法:僅封裝了where和預設的order by以及分頁,支援模糊查詢
     *
     * @param t     要查的表
     * @param open  是否啟用排序
     * @param flag  排序要求
     * @param e     分頁物件
     * @param vague 是否進行模糊查詢
     * @return
     */
    @Override
    public List<T> select(T t, boolean open, boolean flag, E e, boolean vague,String order) throws Exception {
        //獲取表名註解
        Table table = EntityClass.getAnnotation(Table.class);
        String tableName = table.name();
        //取的域物件並做遍歷處理
        Field[] fields = EntityClass.getDeclaredFields();
        //存放where語句後的查詢條件的Map
        Map<String, Object> whereMap = new HashMap<String, Object>();
        List<Object> sonObjectList = new ArrayList<>();
        //存放排序條件的集合
        List<String> orderList = new ArrayList<String>();
        for (Field field : fields) {
            field.setAccessible(true);//一定要施暴
            //獲取屬性值,判斷是否為空,拼接where條件
            if (field.isAnnotationPresent(Column.class)) {
/*                Method method=clazz.getMethod("get"+getMethodName(field.getName()));Object value=method.invoke(object);PropertyDescriptor pd = new PropertyDescriptor(field.getName(),object.getClass());Object value=pd.getReadMethod().invoke(object);String verificationValue= (String) field.get(object);*/
                Method method = EntityClass.getMethod("get" + getMethodName(field.getName()));
                String verificationValue = String.valueOf(method.invoke(t));
                if (!verificationValue.equals("null")) {
                    //不為空,是查詢條件
                    Object value = field.get(t);
                    Class clazz = value.getClass();
                    Column column = field.getAnnotation(Column.class);
                    String key = column.name();
                    whereMap.put(key, value);
                }
            }
            //拼接排序條件
            if (field.isAnnotationPresent(OrderItem.class)) {
                OrderItem orderItem = field.getAnnotation(OrderItem.class);
                orderList.add(orderItem.name());
            }
        }
        //拼接分頁
        Integer[] limitCondition = new Integer[2];
        Field[] fields1 = EntityClass1.getDeclaredFields();
        for (Field field : fields1) {
            if (field.isAnnotationPresent(Column.class)) {
                Column column = field.getAnnotation(Column.class);
                String limitName = column.name();
                Method method = EntityClass1.getMethod("get" + getMethodName(field.getName()));
                Integer value = (Integer) method.invoke(e);
                if (value != null) {
                    if (limitName.equals("currentPage")) {
                        limitCondition[0] = value;
                    }
                    if (limitName.equals("currentCount")) {
                        limitCondition[1] = value;
                    }
                }
            }
        }
        if (limitCondition[0] != null && limitCondition[1] != null) {
            limitCondition[0] = limitCondition[1] * (limitCondition[0] - 1);
        }
        //集合準備完畢,開始拼接sql
        StringBuilder sql = new StringBuilder("");
        sql.append("select * from ").append(tableName);
        //判斷whereMap是否為空來進行條件查詢
        List<Object> valueList = new ArrayList<>();
        if (whereMap.size() != 0) {
            sql.append(" where ");
            for (Map.Entry<String, Object> entry : whereMap.entrySet()) {
                if (vague) {
                    if (entry.getValue() instanceof String) {
                        sql.append(entry.getKey() + " like ? and ");
                        valueList.add("%" + entry.getValue() + "%");
                    } else {
                        sql.append(entry.getKey() + "=? and ");
                        valueList.add(entry.getValue());
                    }
                } else {
                    sql.append(entry.getKey() + "=? and ");
                    valueList.add(entry.getValue());
                }
            }
            sql.delete(sql.length() - 5, sql.length());
        }
        //判斷是否進行預設排序
        if (open) {
            sql.append(" order by ");
            if (orderList.size() != 0) {
                for (String str : orderList) {
                    sql.append(str).append(",");
                }
                sql.delete(sql.length() - 1, sql.length());
            }
        }
        //是否進行自定義排序
        if(!(order==null || order.equals(""))){
            if (open){
                boolean f=true;
                for (String str : orderList) {
                    if (str.equals(order)){
                        f=false;
                        break;
                    }
                }
                if (f){
                    sql.append(",").append(order+" ");
                }
            }else {
                sql.append(" order by ").append(order+" ");
            }
        }
        if (open || !(order==null || order.equals(""))){
            sql.append(" ").append(flag == true ? "asc" : "desc").append(" ");
        }
        //判斷是否分頁
        if (limitCondition[0] != null && limitCondition[1] != null) {
            sql.append("limit").append(" ").append(limitCondition[0]).append(",").append(limitCondition[1]);
        }
        //SQL拼接完畢,開始執行查詢
        PreparedStatement preState = null;
        Connection connection = null;
        ResultSet resultSet = null;
        try {
            connection = JDBCUtils.getConnection();
            //編譯
            preState = connection.prepareStatement(String.valueOf(sql));
            preState = JDBCUtils.setObject(preState, valueList.toArray());
            resultSet = preState.executeQuery();
            //通過反射將resultSet封裝為物件集
            List<T> resultList = new ArrayList<>();
            int m=resultSet.getRow();
            while (resultSet.next()) {
                T resultObject = EntityClass.newInstance();
                for (Field field : fields) {
                    field.setAccessible(true);
                    if (field.isAnnotationPresent(Column.class)) {
                        String columnName = field.getAnnotation(Column.class).name();
                        Object fieldValue = resultSet.getObject(columnName);
                        field.set(resultObject, fieldValue);
                    }
                }
                for (Field field : fields) {
                    //處理實體類註解,採用迭代
                    if (field.isAnnotationPresent(Entity.class)) {
                        //獲取註解物件,獲取對應的屬性值
                        Entity entity = field.getAnnotation(Entity.class);
                        String idName = entity.field();
                        Method method = EntityClass.getMethod("get" + getMethodName(idName));
                        String verificationValue = String.valueOf(method.invoke(t));
                        Class clazz = Class.forName(entity.address());
                        Object sonObject = clazz.newInstance();
                        Object value;
                        if (!verificationValue.equals("null")) {
                            //這是條件查詢
                            value = method.invoke(t);
                        } else {
                            //非條件查詢
                            value = method.invoke(resultObject);
                        }
                        Field[] sonFields = sonObject.getClass().getDeclaredFields();
                        //獲取子實體類的id屬性
                        for (Field field1 : sonFields) {
                            field1.setAccessible(true);//一定要施暴
                            //獲取外來鍵
                            if (field1.isAnnotationPresent(Key.class)) {
                                if (field1.getAnnotation(Key.class).farther().equals(entity.table())) {
                                    field1.set(sonObject, value);
                                    break;
                                }
                            }
                        }
                        sonObjectList = sonSelect(sonObject);
                        //封裝
                        //判斷當前域物件的型別用getSimpleName
                        Class c = field.getType();
                        String name = c.getSimpleName();
                        if ( sonObjectList != null  && sonObjectList.size() != 0) {
                            if ("List".equals(name)) {
                                field.set(resultObject, sonObjectList);
                            } else {
                                field.set(resultObject, sonObjectList.get(0));
                            }
                        }
                    }
                }
                resultList.add(resultObject);
            }
            return resultList;
        } catch (SQLException e1) {
            e1.printStackTrace();
            return null;
        } finally {
            //關閉資源
            JDBCUtils.close(connection, preState, resultSet);
        }
    }

    /**
     * 迭代處理類
     */
    public List<Object> sonSelect(Object object) throws Exception {
        Class clazz = object.getClass();
        Table table = (Table) clazz.getAnnotation(Table.class);
        String tableName = table.name();
        Field[] fieldList = clazz.getDeclaredFields();
        Map<String, Object> whereMap = new HashMap<>();
        List<Object> sonObjectList = new ArrayList<>();
        for (Field field : fieldList) {
            field.setAccessible(true);
            //普通型別註解
            if (field.isAnnotationPresent(Column.class)) {
                Method method = clazz.getMethod("get" + getMethodName(field.getName()));
                String verificationValue = String.valueOf(method.invoke(object));
                if (!verificationValue.equals("null")) {
                    Object value = method.invoke(object);
                    String key = field.getAnnotation(Column.class).name();
                    whereMap.put(key, value);
                }
            }
        }
        //集合準備完畢,開始拼接sql
        StringBuilder sql = new StringBuilder("");
        sql.append("select * from ").append(tableName);
        List<Object> valueList = new ArrayList<>();
        if (whereMap.size() != 0) {
            sql.append(" where ");
            for (Map.Entry<String, Object> entry : whereMap.entrySet()) {
                sql.append(entry.getKey() + "=? and ");
                valueList.add(entry.getValue());
            }
            sql.delete(sql.length() - 5, sql.length());
        }
        //SQL拼接完畢,開始執行查詢
        PreparedStatement preState = null;
        Connection connection = null;
        ResultSet resultSet = null;
        try {
            connection = JDBCUtils.getConnection();
            //編譯
            preState = connection.prepareStatement(String.valueOf(sql));
            preState = JDBCUtils.setObject(preState, valueList.toArray());
            resultSet = preState.executeQuery();
            //通過反射將resultSet封裝為物件集
            List<Object> resultList = new ArrayList<>();
            while (resultSet.next()) {
                Object resultObject = clazz.newInstance();
                for (Field field : fieldList) {
                    field.setAccessible(true);
                    //普通註解
                    if (field.isAnnotationPresent(Column.class)) {
                        String columnName = field.getAnnotation(Column.class).name();
                        Object fieldValue = resultSet.getObject(columnName);
                        field.set(resultObject, fieldValue);
                    }
                }
                for (Field field : fieldList) {
                    //處理實體類註解,採用迭代
                    if (field.isAnnotationPresent(Entity.class)) {
                        Entity entity = field.getAnnotation(Entity.class);
                        String idName = entity.field();
                        Method method = clazz.getMethod("get" + getMethodName(idName));
                        String verificationValue = String.valueOf(method.invoke(object));
                        Class clazz1 = Class.forName(entity.address());
                        Object sonObject = clazz1.newInstance();
                        Object value;
                        if (!verificationValue.equals("null")) {
                            //條件查詢
                            value = method.invoke(object);
                        } else {
                            value = method.invoke(resultObject);
                        }
                        Field[] sonFields = sonObject.getClass().getDeclaredFields();
                        for (Field field2 : sonFields) {
                            field2.setAccessible(true);//一定要施暴
                            if (field2.isAnnotationPresent(Key.class)) {
                                if (field2.getAnnotation(Key.class).farther().equals(entity.table())) {
                                    field2.set(sonObject, value);
                                    break;
                                }
                            }
                        }
                        sonObjectList = sonSelect(sonObject);
                        //封裝
                        //判斷註解是否是加在集合上的
                        //判斷當前域物件的型別用getSimpleName
                        Class c = field.getType();
                        String name = c.getSimpleName();
                        if (sonObjectList != null   && sonObjectList.size() !=0) {
                            if ("List".equals(name)) {
                                field.set(resultObject, sonObjectList);
                            } else {
                                field.set(resultObject, sonObjectList.get(0));
                            }
                        }
                    }
                }
                resultList.add(resultObject);
            }
            return resultList;
        } catch (SQLException e1) {
            e1.printStackTrace();
            return null;
        } finally {
            //關閉資源
            JDBCUtils.close(connection, preState, resultSet);
        }
    }

 

這樣,在查詢一級類的時候就能把二級類的資訊也查詢出來了,同時可以無限迭代查詢。

程式碼下載地址:https://download.csdn.net/download/qq_34295546/10225638