import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.ztools.annotation.BeanTable;
import com.ztools.annotation.BeanTableField;
public class GenerateBatchInsertSQL {
// bean 转为 insert into table() values();
// 需要分批处理
public enum SQL {sql, values}
private static final int BATCH_SIZE = 100;// 每100条数据组成一条插入数据
private static int count = 0;
private static final List<String> properties = new ArrayList<>();// 存储bean属性列表
private static final Map<String, Method> methodMap = new HashMap<>();
// 数据很多时用,分批次处理,每批次100条
public static <T> List<Map<SQL, Object>> largeBatchInsertSQL(Class<T> beanClass, List<T> beans) {
List<Map<SQL, Object>> res = new ArrayList<>();
if (beans == null || beans.size() == 0) {
return res;
}
int size = beans.size();
Map<SQL, Object> map;
if (size <= BATCH_SIZE) {
map = smallBatchInsertSQL(beanClass, beans);
res.add(map);
return res;
}
for (int i = 0; i < (size / BATCH_SIZE) + 1; i++) {
if (BATCH_SIZE * i == size) {// 总数刚好是批次的倍数时
continue;
}
if (BATCH_SIZE * (i + 1) >= size) {
map = smallBatchInsertSQL(beanClass, beans.subList(BATCH_SIZE * i, size));
} else {
map = smallBatchInsertSQL(beanClass, beans.subList(BATCH_SIZE * i, BATCH_SIZE * (i + 1)));
}
res.add(map);
}
return res;
}
private static <T> Map<SQL, Object> smallBatchInsertSQL(Class<T> beanClass, List<T> beans) {
Map<SQL, Object> map = new HashMap<>();
if (beans == null || beans.size() == 0) {
return map;
}
String sql = generateInsertSQLByBean(beanClass, beans);
Object[] objs = generateParamValue(beanClass, beans);
map.put(SQL.sql, sql);
map.put(SQL.values, objs);
return map;
}
// insert into table(?,?,?) values(?,?,?)
private static <T> String generateInsertSQLByBean(Class<T> beanClass, List<T> beans) {
count = beans.size();
String table = getBeanTableName(beanClass);
String columns = getColumns(beanClass);
String placeholder = getPlaceholder();
return "insert into " + table + "(" + columns + ") values " + placeholder;
}
private static <T> Object[] generateParamValue(Class<T> beanClass, List<T> beans) {
Object[] objects = new Object[count * properties.size()];
putGetMethodsToContainer(beanClass);
int i = 0;
for (T bean : beans) {
for (String name : properties) {
try {
if (methodMap.get(name) != null) {
objects[i] = methodMap.get(name).invoke(bean);
}
} catch (Exception e) {
e.printStackTrace();
}
i++;
}
}
return objects;
}
private static <T> String getBeanTableName(Class<T> beanClass) {
return beanClass.getAnnotation(BeanTable.class).table();
}
private static <T> String getColumns(Class<T> beanClass) {
Field[] fields = beanClass.getDeclaredFields();
StringBuilder columns = new StringBuilder();
if (fields.length <= 0)
return columns.toString();
properties.clear();
for (Field field : fields) {
if (field.getDeclaredAnnotation(BeanTableField.class) == null) {
continue;
}
columns.append(field.getDeclaredAnnotation(BeanTableField.class).column());
columns.append(",");
properties.add(field.getName().toLowerCase());
}
return columns.substring(0, columns.length() - 1);
}
private static String getPlaceholder() {
StringBuffer values = new StringBuffer();
for (int i = 0; i < count; i++) {
values.append("(");
for (int j = 0; j < properties.size(); j++) {
values.append("?,");
}
values = new StringBuffer(values.substring(0, values.length() - 1));
values.append("),");
}
return values.substring(0, values.length() - 1);
}
private static <T> void putGetMethodsToContainer(Class<T> beanClass) {
Method[] methods = beanClass.getDeclaredMethods();
String name;
methodMap.clear();
for (Method method : methods) {
name = method.getName();
if (name.startsWith("get")) {
methodMap.put(name.substring(3).toLowerCase(), method);
}
}
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeanTable {
public String table();
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface BeanTableField {
String column();
}