反射生成insert多个对象的sql语句

郑斌Blog 郑斌Blog     2022-08-31     332

关键词:

场景

下订单时,将生成一个订单和对应的多个订单详情,即一个 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, 鱼香茄子, 少放油]

 

如何插入多个insert sql语句

】如何插入多个insertsql语句【英文标题】:Howtoinsertmultipleinsertsqlstatement【发布时间】:2019-01-2406:53:05【问题描述】:有一个表Person(id,name)。我在人员表中插入了1000多条记录。id和name都应该是唯一的。我写了这样的东西INSERTALLINTO... 查看详情

为 SQL Server 表自动生成 INSERT 语句的最佳方法是啥?

】为SQLServer表自动生成INSERT语句的最佳方法是啥?【英文标题】:Whatisthebestwaytoauto-generateINSERTstatementsforaSQLServertable?为SQLServer表自动生成INSERT语句的最佳方法是什么?【发布时间】:2009-06-1117:42:28【问题描述】:我们正在编写一... 查看详情

jdbc-根据resultset返回值生成insert-sql语句

线上数据导线下数据时需要,导出insert的sql语句解析resultset中的 元数据metadata,获取结果集的 column名及对应的columnvalue,拼接成sql@OverridepublicMetaDatamapRow(ResultSetrs,introwNum)throwsSQLExceptionMetaDatadata= 查看详情

sqlsever将sqlsever中的一个数据表的数据导出为insert语句

...据表,想要将这张数据表中的数据 转化成一个一个的insert语句存储在txt的文档中,那么不论走到那里这个insert语句一执行,我们就能将这个数据表中的数据插入到另一个地方了。1》在新建查询中,创建一个对象,这个对象... 查看详情

sql的insert怎么可以一次插入多项数据?

...定的默认值。由于Microsoft®SQLServer™为以下类型的列生成值,INSERT语句将不为这些类型的列指定值:具有IDENTITY属性的列,该属性为列生成值。有默认值的列,该列用NEWID函数生成一个唯一的GUID值。计算列。这些是虚拟列,... 查看详情

mybatis自动生成的insert语句有啥区别

参考技术A主键是自动赋值在对象中的。比如对象User,属性id为主键,name,ageUseruser=newUser();user.setName("test");user.setAge(16);调用mybatis的insert(user);返回值是1,该条记录的主键通过user.getId();即可获龋 查看详情

mybatis自动生成的insert语句有啥区别

参考技术A主键是自动赋值在对象中的。比如对象User,属性id为主键,name,ageUseruser=newUser();user.setName("test");user.setAge(16);调用mybatis的insert(user);返回值是1,该条记录的主键通过user.getId();即可获龋 查看详情

为啥 EF Core 2.0 会生成多个重复的 SQL 语句?

】为啥EFCore2.0会生成多个重复的SQL语句?【英文标题】:WhyisEFCore2.0generatingmultipleduplicateSQLstatements?为什么EFCore2.0会生成多个重复的SQL语句?【发布时间】:2022-01-1314:33:16【问题描述】:我在其服务层中继承了一个带有EntityFramewor... 查看详情

mybatis详解

...式来实现SQL语句的配置和映射,同时还支持动态SQL语句的生成,可以根据不同的条件生成不同的SQL语句。二、核心组件MyBatis的核心组件包括:SqlSessionFactory:SqlSessionFactory是MyBatis的核心接口,它用于创建SqlSession对象,SqlSession是M... 查看详情

c#通过反射生成sql

1、定义特性标志表或表字段publicclassExtendAttribute///<summary>///表示在自动生成SQL语句时,不处理该字段///</summary>[AttributeUsage(AttributeTargets.Property)][Serializable]publicclassExcludeFieldAttribute:Attribute 查看详情

多个 INSERT 语句与具有多个 VALUES 的单个 INSERT

】多个INSERT语句与具有多个VALUES的单个INSERT【英文标题】:MultipleINSERTstatementsvs.singleINSERTwithmultipleVALUES【发布时间】:2012-01-2723:31:20【问题描述】:我正在使用1000个INSERT语句进行性能比较:INSERTINTOT_TESTS(TestId,FirstName,LastName,Age)VA... 查看详情

多个 INSERT 语句与具有多个 VALUES 的单个 INSERT

】多个INSERT语句与具有多个VALUES的单个INSERT【英文标题】:MultipleINSERTstatementsvs.singleINSERTwithmultipleVALUES【发布时间】:2012-01-2723:31:20【问题描述】:我正在使用1000个INSERT语句进行性能比较:INSERTINTOT_TESTS(TestId,FirstName,LastName,Age)VA... 查看详情

mybatis的mapper.xml怎么同时执行多个sql语句

...个方法就可以,要是你指的是<select></select>和<insert></insert>貌似mybatis不能这样使用,因为他一般是一个方法对应一个sql语句,你想是想一个方法调用两个sql语句,要么就是在一个方法里调用那两个方法,这样间... 查看详情

mybatis的mapper.xml怎么同时执行多个sql语句

...个方法就可以,要是你指的是<select></select>和<insert></insert>貌似mybatis不能这样使用,因为他一般是一个方法对应一个sql语句,你想是想一个方法调用两个sql语句,要么就是在一个方法里调用那两个方法,这样间... 查看详情

C# 解析 SQL 语句以查找存储过程中使用的所有 INSERT/UPDATE/DELETE 表

...说,我的目的是找到所有参与INSERT/UPDATE/DELETE语句的表并生成结构化格式。到目前为止,这就是我 查看详情

基于反射和泛型的编程

  基于反射和泛型的编程,泛型是容器话的思路统过泛型对象或泛型方法,管理实际要操作的对象,以实现对于实际对象管理的一种编程。  比如导出excel生成报表这种在平台开发中及其普遍的需求,有多个对象有生成报表... 查看详情

利用sql注入

...14.利用此性质,配合ASCII函数可以获得大部分目标的值。生成INSERT错误1.在insert语句的值中填写表不允许的数据,正好这个数据是我们需要的目 查看详情

类的加载机制和反射——使用反射生成jdk动态代理

使用反射生成JDK动态代理1.使用Proxy和InvocationHandler创建动态代理(1)Proxy提供了用于创建动态代理类和动态代理对象的静态方法,他也是所有动态代理类的父类。(2)如果在程序中为一个或多个接口动态的生成实现类,就可以... 查看详情