反射生成 INSERT 多個對象的 SQL 語句(批量插入)


場景

下訂單時,將生成一個訂單和對應的多個訂單詳情,即一個 order 對象和多個 orderinfo 對象。

多個 orderinfo 對象在落庫時,DAO 層向上層調用的接口入參是 List<OrderInfo>,那么接口的實現就需要將 List<OrderInfo> 轉為一條完整的 SQL 語句。

如:

insert into person(name, age, info) values ('18歲的鄭斌', 18, '大一'),('22歲的鄭斌', 22, '大四');

下面通過反射的方法,生成帶有占位符的 SQL,和填充占位符的數據數組。

源碼

private static void insertObject(List<?> objectList) throws IllegalAccessException {
        /**
         * 比如:
         * SQL 語句:insert into person(name, age, info) values ('...', '...', '...');
         * 其中 values 改為占位符:
         * SQL 語句:insert into person(name, age, info) values (?, ?, ?);
         * 再獲取所有的數據值 Object 數組
         * [zhengbin, 21, 要畢業了]
         */
        // 確定占位符的個數(即對象中不為 null 的字段個數)
        int columnNum = 0;
        // 插入數據的列名
        StringBuilder columns = new StringBuilder("(");
        // 填充占位符的值(即對象中不為null的字段的值)
        List<Object> valuesList = new ArrayList<Object>();
        // 如果為空則不執行
        if (CollectionUtil.isEmpty(objectList)) {
            return;
        }
        // 通過 List 中的第一個 Object,確定插入對象的字段
        Object object = objectList.get(0);
        Class clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if (field.get(object) != null) {
                columnNum++;
                columns.append(field.getName()).append(", ");
                valuesList.add(field.get(object));
            }
        }
        columns.replace(columns.lastIndexOf(", "), columns.length(), ")");

        // 獲取所有的值
        for (int i = 1; i < objectList.size(); i++) {
            for (Field field : fields) {
                field.setAccessible(true);
                if (field.get(objectList.get(i)) != null) {
                    valuesList.add(field.get(objectList.get(i)));
                }
            }
        }
        // 確定一個 Object 的占位符 '?'
        StringBuilder zhanweifuColumn = new StringBuilder("(");
        for (int i = 0; i < columnNum; i++) {
            zhanweifuColumn.append("?, ");
        }
        zhanweifuColumn.replace(zhanweifuColumn.lastIndexOf(", "), zhanweifuColumn.length(), ")");

        // 確定所有的占位符
        int objectNum = objectList.size();
        StringBuilder zhanweifu = new StringBuilder();
        for (int j = 0; j < objectNum; j++) {
            zhanweifu.append(zhanweifuColumn.toString()).append(", ");
        }
        zhanweifu.replace(zhanweifu.lastIndexOf(", "), zhanweifu.length(), "");

        // 生成最終 SQL
        String sql = "INSERT INTO " + object.getClass().getSimpleName().toLowerCase() + " " + columns + " VALUES " + zhanweifu.toString();
        System.out.println(sql);
        System.out.println(valuesList);
    }

測試

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        List<OrderInfo> orderInfos = new ArrayList<OrderInfo>();
        OrderInfo orderInfo1 = new OrderInfo();
        orderInfo1.setOrder_id(10);
        orderInfo1.setFood_id(1);
        orderInfo1.setPrice(18d);
        orderInfo1.setNum(1);
        orderInfo1.setTotal_price(18d);
        orderInfo1.setFood_name("宮保雞丁");
        orderInfo1.setRemark("少放辣椒");

        OrderInfo orderInfo2 = new OrderInfo();
        orderInfo2.setOrder_id(10);
        orderInfo2.setFood_id(1);
        orderInfo2.setPrice(16d);
        orderInfo2.setNum(1);
        orderInfo2.setTotal_price(16d);
        orderInfo2.setFood_name("魚香茄子");
        orderInfo2.setRemark("少放油");

        orderInfos.add(orderInfo1);
        orderInfos.add(orderInfo2);

        insertObject(orderInfos);
    }
View Code

測試結果:

INSERT INTO orderinfo (order_id, food_id, price, num, total_price, food_name, remark) VALUES (?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?)
[10, 1, 18.0, 1, 18.0, 宮保雞丁, 少放辣椒, 10, 1, 16.0, 1, 16.0, 魚香茄子, 少放油]

 


免責聲明!

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



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