批量导入思路
最近遇到一个需要批量导入数据问题。后来考虑运用反射做成一个工具类,思路是首先定义注解接口,在bean类上加注解,运行时通过反射获取传入Bean的注解,自动生成需要插入DB的SQL,根据设置的参数值批量提交。不需要写具体的SQL,也没有DAO的实现,这样一来批量导入的实现就和具体的数据库表彻底解耦。实际批量执行的SQL如下:
insert into company_candidate(company_id,user_id,card_id,facebook_id,type,create_time,weight,score) VALUES (?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE type=?,weight=?,score=?
第一步,定义注解接口
注解接口Table中定义了数据库名和表名。RetentionPolicy.RUNTIME表示该注解保存到运行时,因为我们需要在运行时,去读取注解参数来生成具体的SQL。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
/**
* 表名
* @return
*/
String tableName() default "";
/**
* 数据库名称
* @return
*/
String dbName();
}
注解接口TableField中定义了数据库表名的各个具体字段名称,以及该字段是否忽略(忽略的话就会以数据库表定义默认值填充,DB非null字段的注解不允许出现把ignore注解设置为true)。update注解是在主键在DB重复时,需要更新的字段。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TableField {
/**
* 对应数据库字段名称
* @return
*/
String fieldName() default "";
/**
* 是否是主键
* @return
*/
boolean pk() default false;
/**
* 是否忽略该字段
* @return
*/
boolean ignore() default false;
/**
* 当数据存在时,是否更新该字段
* @return
*/
boolean update() default false;
}
第二步,给Bean添加注解
给Bean添加注解(为了简洁省略了import和set/get方法以及其他属性),@TableField(fieldName = "company_id")表示companyId字段对应DB表的字段名为"company_id",其中updateTime属性的注解含有ignore=true,表示该属性值会被忽略。另外serialVersionUID属性由于没有@TableField注解,在更新DB时也会被忽略。
代码如下:
@Table(dbName = "company", tableName = "company_candidate")
public class CompanyCandidateModel implements Serializable{
private static final long serialVersionUID = -1234554321773322135L;
@TableField(fieldName = "company_id")
private int companyId;
@TableField(fieldName = "user_id")
private int userId;
//名片id
@TableField(fieldName = "card_id")
private int cardId;
//facebookId
@TableField(fieldName = "facebook_id")
private long facebookId;
@TableField(fieldName="type", update = true)
private int type;
@TableField(fieldName = "create_time")
privat