id,姓名,年龄,职位,地址,家庭情况,电话,注册时间
字段 | id | 姓名 | 年龄 | 职位 | 地址 | 家庭情况 | 电话 | 注册时间 |
oracle类型 | NUMBER(19,0) | VARCHAR2(255 CHAR) | NUMBER(9,0) | VARCHAR2(255 CHAR) | VARCHAR2(255 CHAR) | VARCHAR2(255 CHAR) | VARCHAR2(255 CHAR) | NUMBER(19,0) |
java类型 | long | String | int | String | String | String | String | long |
CREATE TABLE MY_CUSTOMER
(
"ID" NUMBER(19,0) NOT NULL PRIMARY KEY,
"NAME" VARCHAR2(255 CHAR) DEFAULT '_' NOT NULL ,
"AGE" NUMBER(9,0) DEFAULT 18 NOT NULL ,
"POSITION" VARCHAR2 (255 CHAR) DEFAULT '_' ,
"ADDRESS" VARCHAR2(255 CHAR) DEFAULT '_' ,
"SITUATION" VARCHAR2(255 CHAR) DEFAULT '_',
"PHONENUMBER" VARCHAR2(255 CHAR) DEFAULT '_',
"REGISTERTIME" NUMBER(19,0)
)
COMMENT ON COLUMN "MY_CUSTOMER"."ID" IS '主键';
COMMENT ON COLUMN "MY_CUSTOMER"."NAME" IS '姓名';
COMMENT ON COLUMN "MY_CUSTOMER"."AGE" IS '年龄';
COMMENT ON COLUMN "MY_CUSTOMER"."POSITION" IS '职位';
COMMENT ON COLUMN "MY_CUSTOMER"."ADDRESS" IS '地址';
COMMENT ON COLUMN "MY_CUSTOMER"."SITUATION" IS '家庭情况';
COMMENT ON COLUMN "MY_CUSTOMER"."PHONENUMBER" IS '电话';
COMMENT ON COLUMN "MY_CUSTOMER"."REGISTERTIME" IS '注册时间';
create sequence MY_CUSTOMER_IP_SEQ
minvalue 1 -- 最小值为1
nomaxvalue -- 不设置最大值
increment by 1 -- 增长数字(步长为1)
start with 1 -- 开始数字为1
nocache; -- 不缓存
@Data
public class MyCustomer implements Serializable {
@ExcelIgnore
private int id;
@ExcelProperty("姓名")
private String name ;
@ExcelProperty("年龄")
private Integer age ;
@ExcelProperty("职位")
private String position;
@ExcelProperty("地址")
private String address;
@ExcelProperty("家庭情况")
private String situation;
@ExcelProperty("电话号码")
private String phoneNumber;
@ExcelIgnore
private Long registerTime;
@ExcelProperty("注册时间")
@ColumnWidth(20)
private String registerStr;
}
需要实现序列化,因为无论是使用dubbo还是easyExcel的时候都需要序列化
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MyCustomerQuery implements Serializable {
/**通过日期来筛选,开始时间*/
private String startTime ;
/**通过日期来筛选,结束时间*/
private String endTime ;
/**开始时间对应的时间戳*/
private Long begin;
/**结束时间对应的时间戳*/
private Long end;
/**姓名*/
private String name;
}
需要实现序列化
@Mapper
public interface MyCustomerDao {
/**
* insertMyCustomerBatch 批量插入客户
*/
int insertMyCustomerBatch(@Param("myCustomers") List myCustomers) ;
/**
* 批量查询数据
*/
List queryMyCustomerBatch(MyCustomerQuery myCustomerQuery);
}
这里还需要配置包扫描,否者无法找到对应的mapper
insert into MY_CUSTOMER
(id,NAME,AGE,POSITION,ADDRESS,SITUATION,PHONENUMBER,REGISTERTIME)
select MY_CUSTOMER_IP_SEQ.nextval ,a.* from (
select
#{customer.name} as name,
'-' as name,
#{customer.age} as age,
'-' as age,
#{customer.position} as position,
'-'as position,
#{customer.address} as address,
'-' as address,
#{customer.situation} as situation,
'-' as situation,
#{customer.phoneNumber} as phonenumber,
'-' as phonenumber,
#{customer.registerTime} as registertime
'-' as registertime
from DUAL
) a
mybatis动态标签foreach中collection的值需要我们指定,这个值在dao方法中使用@Param指定
在最后一个if判断的时候不需要使用 ‘,’逗号,因为在拼接SQL的时候最后一个参数不需要逗号,如果写了会报 为知from错误
这里的dual是oracle中虚拟表,只有一行
这里使用union分割,目的是将我们使用dual得到的一行行数据拼接起来组成一个表
这里的MY_CUSTOMER_IP_SEQ.nextval就是获取序列的下一个值,这样就可以保证id自增
oracle特殊语法,可以直接通过insert 语句直接将一张虚拟表的数据插入到数据库中,不需要 insert value
public interface MyCustomerService {
/***
* easyexcel批量导出
* @param myCustomerQuery 查询参数,根据姓名和起始时间模糊查询
* @return java.util.List
*/
List queryMyCustomerBatch(MyCustomerQuery myCustomerQuery);
/**
* 从excel中批量插入数据库
* @param myCustomers
* @return java.lang.Integer
*/
public Boolean insertMyCustomerBatch(List myCustomers) ;
}
@Service("myCustomerService")
public class MyCustomerServiceImpl implements MyCustomerService{
@Autowired
private MyCustomerDao myCustomerDao;
@Override
public List queryMyCustomerBatch(MyCustomerQuery myCustomerQuery) {
List myCustomers = new ArrayList<>();
if (myCustomerQuery !=null) {
myCustomers = myCustomerDao.queryMyCustomerBatch(myCustomerQuery);
if (!CollectionUtils.isEmpty(myCustomers)){
for (MyCustomer customer : myCustomers){
//注册时间转换成字符串
customer.setRegisterStr(DateUtils.formatDate(customer.getRegisterTime()));
}
}
}
return myCustomers;
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public Boolean insertMyCustomerBatch(List myCustomers) {
int flag = myCustomerDao.insertMyCustomerBatch(myCustomers);
return flag != 0;
}
}
我的项目是写在dubbo应用中的,这里的@Service注解需要带上value属性,否则启动dubbo的时候会报错
public interface MyCustomerAO {
void addMyCustomerBatchToExcel(MyCustomerQuery myCustomerQuery, HttpServletResponse response) throws IOException;
void insertMyCustomerBatchFromExcel(MyCustomerQuery myCustomerQuery, MultipartFile file) throws IOException;
}
@Component
public class myCustomerAOImpl implements MyCustomerAO {
@Autowired
MyCustomerService myCustomerService;
@Override
public void addMyCustomerBatchToExcel(MyCustomerQuery myCustomerQuery, HttpServletResponse response) throws IOException {
// 获取需要查询写入到excel中的Customer集合
List myCustomers = myCustomerService.queryMyCustomerBatch(myCustomerQuery);
//调用方法,将数据写入excel
EasyExcel.write(response.getOutputStream(),MyCustomer.class).sheet("写操作").doWrite(myCustomers);
}
@Override
public void insertMyCustomerBatchFromExcel(MyCustomerQuery myCustomerQuery, MultipartFile file) throws IOException {
// 调用easyExcel自定义监听器,执行批量导入操作
EasyExcel.read(file.getInputStream(), MyCustomer.class, new ExcelListener(myCustomerService)).sheet().doRead();
}
}
public class ExcelListener extends AnalysisEventListener {
private MyCustomerService myCustomerService;
public ExcelListener(){
}
/**因为继承了AnalysisEventListener,而 AnalysisEventListener底层实现了过滤器,
* 故这个类不能交给spring管理,所以这能通过构造方法注入
* */
public ExcelListener(MyCustomerService myCustomerService){
this.myCustomerService = myCustomerService;
}
/**定义了一个list,用于将每一行的数据存储起来,我们在dao层直接批量插入list*/
private final List totalCustomerBatch = new ArrayList<>();
@Override
public void invoke(MyCustomer data, AnalysisContext context) {
// 将excel中日期格式字符串转换为long类型的
String registerStr = data.getRegisterStr();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date = simpleDateFormat.parse(registerStr);
data.setRegisterTime(date.getTime());
} catch (ParseException e) {
throw new RuntimeException(e);
}
// 修改完日期格式以后将所有的customer放入list,全部执行完以后执行批量查询
totalCustomerBatch.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
//执行批量插入
myCustomerService.insertMyCustomerBatch(totalCustomerBatch);
}
}
@RequestMapping("/mycustomer")
@Controller
public class MyCustomerController {
@Autowired
private MyCustomerAO myCustomerAO;
/***
* 进入到我的客户页面
* @return java.lang.String
*/
@RequestMapping("toExcelPage")
public String toMyCustomerPage () {
return "demo/testMyCustomer";
}
/***
* easyExcel写操作,将数据写入excel
* @param myCustomerQuery 模糊查询对象,根据姓名、开始时间和结束时间匹配
* @param response 响应对象,将查询到的数据会写
*/
@RequestMapping("toExcel")
public void addMyCustomerBatchToExcel(MyCustomerQuery myCustomerQuery ,HttpServletResponse response) throws ParseException, IOException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//将前端传来的日期时间转换成时间错,用于限制日期的范围
if (!StringUtil.isBlank(myCustomerQuery.getStartTime())) {
myCustomerQuery.setBegin(simpleDateFormat.parse(myCustomerQuery.getStartTime()).getTime());
}
if (!StringUtil.isBlank(myCustomerQuery.getEndTime())) {
myCustomerQuery.setBegin(simpleDateFormat.parse(myCustomerQuery.getEndTime()).getTime());
}
//设置response的格式
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyExcel没有关系
String fileName = URLEncoder.encode("userInfo", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
myCustomerAO.addMyCustomerBatchToExcel(myCustomerQuery,response);
}
/***
* easyExcel文件读操作,将excel文件中的内容读入数据库
* @param myCustomerQuery
* @param file
*/
@RequestMapping("toDatabase")
public void selectMyCustomerFromExcel(MyCustomerQuery myCustomerQuery,
@RequestParam("importExcel") MultipartFile file) throws IOException {
//获取文件的路径
String fileName = file.getOriginalFilename();
myCustomerAO.insertMyCustomerBatchFromExcel(myCustomerQuery ,file);
}
}
dubbo-consumer.xml
dubbo-provider.xml
Document
我的前端页面是通过volecity与后端交互的,所以文件的后缀是.ms,这里需要根据自己的引擎修改
到这里代码部分已经写完了,我们需要测试我们的功能就需要向我们的oracle中添加几条测试数据
INSERT into MY_CUSTOMER (id,name,age,POSITION,ADDRESS,SITUATION,PHONENUMBER,REGISTERTIME) values (MY_CUSTOMER_IP_SEQ.nextval,'张三',18,'','','','',1678348319000);
INSERT into MY_CUSTOMER (id,name,age,POSITION,ADDRESS,SITUATION,PHONENUMBER,REGISTERTIME) values (MY_CUSTOMER_IP_SEQ.nextval,'李四',19,'','','','',1678348319000);