1.前言
因为公司业务的需要,需要写一个定时循环插入数据的脚本,本人只是个小菜鸡,所以用的技术都是基于公司的原有框架选择的较简单的技术,并且之前没有了解过QueryDsl,所以这次的blog也是记录下自己学习QueryDsl的过程.
2.需求
定时查询MYSQL数据库的部门和人员编码List,按照部门/人员为单位插入伪数据,数据尽量真实
3.代码实现
1.POM.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.41</version>
</dependency>
<!-- ojdbc驱动 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>compile</scope>
</dependency>
<!--QueryDsl begin -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-spring</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-codegen</artifactId>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
2.plugin插件
<!--实现QueryDsl的插件 红色字体为compile文件存放路径-->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
3.定义实体类并编译
@Entity
@Table(name = "department")
@Data
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long create_dept_id;
private Long create_time;
private Long create_id;
private Integer status;
private Long update_time;
private Long updater_id;
private String create_dept_name;
private String creator_name;
private String updater_name;
private Integer level;
private String path;
private Long sort_index;
private String business_types;
private String code;
private String description;
private String district;
private String full_name;
private String name;
private String police_type;
@ManyToOne(fetch = FetchType.EAGER, targetEntity = Department.class)
@JoinColumn(name = "parent_id")
private Department parent;
}
4.使用QueryDsl查询MYSQL数据库数据-定义数据源
/**
* dsl数据源配置-mysql
*/
@Configuration
// 不加事务注解会提示Connection is not Transactional
@Transactional
public class DataDsl {
@Bean
public com.querydsl.sql.Configuration querydslConfiguration() {
/**
* 使用mysql数据源,Oracle就使用OracleTemplate模版
*/
SQLTemplates templates = MySQLTemplates.builder()
.printSchema()
.build();
com.querydsl.sql.Configuration configuration = new com.querydsl.sql.Configuration(templates);
/** 若是Oracle数据源就需要如下配置 MySQL不需要
* configuration.setExceptionTranslator(new SpringExceptionTranslator());
* configuration.register(new DateTimeType());
* configuration.register(new LocalDateType());
*/
return configuration;
}
@Bean
public SQLQueryFactory queryFactory() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://数据库地址");
dataSource.setUsername("用户名");
dataSource.setPassword("密码");
Provider<Connection> provider = new SpringConnectionProvider(dataSource);
return new SQLQueryFactory(querydslConfiguration(), provider);
}
}
5.查询MySQL数据并使用JPA+定时器插入将数据插入Oracle
/**
* 定时任务中心
*/
@Slf4j
@Component
//开启springboottask的注解
@EnableScheduling
@Transactional
public class VideoDataJob {
/**
* 查询部门编码
*/
@Scheduled(cron = "${sync.schedule.department.time}")
public List<String> getDepartmentCode() {
if (CONSTANT.equals(department)) {
log.info("VideoDataJob.getDepartmentCode >>>>> begin");
/**
*此处为QueryDsl的查询代码,QDepartment为编译后的实体类
*/
QDepartment department = QDepartment.department;
List<String> list = sqlQueryFactory.select(department.description).from(department).fetch();
return list;
}
return null;
}
/**
* 查询人员编码
*/
@Scheduled(cron = "${sync.schedule.person.time}")
public List<String> getPersonCode() {
if (CONSTANT.equals(person)) {
log.info("VideoDataJob.getPersonCode >>>>> beginQuery");
/**
* 使用的是原生的sql查询sleect from + 条件
*/
QPerson person = QPerson.person;
List<String> list = sqlQueryFactory.select(person.code).from(person).fetch();
}
return null;
}
/**
* 插入违法案件 + 警员code
*/
@Scheduled(cron = "${sync.schedule.violation.time}")
public void violationData() {
if (CONSTANT.equals(violation)) {
long currentTimeMillis = System.currentTimeMillis();
try {
List<String> list = getPersonCode();
for (String personCode : list) {
log.info("VideoDataJob.violationData : INSERT ! " + new Date());
Violation violation = new Violation();
/**
* 新增对象的伪代码
*/
log.info("VideoDataJob.violationData : SUCCESS ! " + new Date());
/**
* 线程休眠30s
*/
Thread.sleep(1000*30);
}
} catch (Exception e) {
log.error("VideoDataJob.violationData exception : " + e.getMessage());
}
log.info("VideoDataJob.violationData cost : " + (System.currentTimeMillis() - currentTimeMillis) + "ms");
}
}
/**
* 插入警情信息 + 部门编码
*/
@Scheduled(cron = "${sync.schedule.policeCase.time}")
public void policeCaseData() {
if (CONSTANT.equals(policeCase)) {
long currentTimeMillis = System.currentTimeMillis();
try {
List<String> list = getDepartmentCode();
for (String departmentCode : list) {
log.info("VideoDataJob.policeCaseData : INSERT ! " + new Date());
PoliceCase policeCase = new PoliceCase();
/**
* 新增对象的伪代码
*/
log.info("VideoDataJob.policeCaseData : SUCCESS ! " + new Date());
/**
* 线程休眠
*/
Thread.sleep(1000*30);
}
} catch (Exception e) {
log.error("VideoDataJob.policeCaseData exception :" + e.getMessage());
}
log.info("VideoDataJob.policeCaseData cost : " + (System.currentTimeMillis() - currentTimeMillis) + "ms");
}
}
private static final String CONSTANT = "true";
@Autowired
private ViolationDao violationDao;
@Autowired
private PoliceCaseDao policeCaseDao;
/**
*注入QueryDsl的数据源工厂
*/
@Autowired
private SQLQueryFactory sqlQueryFactory;
/**
* 获取配置是否打开违法案件定时器
*/
@Value("${sync.schedule.violation.open}")
private String violation;
/**
* 获取配置是否打开警情定时器
*/
@Value("${sync.schedule.policeCase.open}")
private String policeCase;
/**
* 获取配置是否打开部门code查询
*/
@Value("${sync.schedule.department.open}")
private String department;
/**
* 获取配置是否打开警员code查询
*/
@Value("${sync.schedule.person.open}")
private String person;
}
6.application.yml
spring:
application:
name: videoDataSchedule
datasource:
name: dataSource
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@10.255.229.122:11521:XE
username: ***
password: ***
sync:
schedule:
violation:
open: true
time: 0 */1 * * * ?
policeCase:
open: true
time: 0 */1 * * * ?
department:
open: true
time: 0 */1 * * * ?
person:
open: true
time: 0 */1 * * * ?
7.总结
总体这个脚本还是很简单的,逻辑也是很简单,只是自己针对QueryDsl还不是很了解,同时因为Demo里面需要配置MySQL和oracle两个数据源,一开始的思路错了,一直纠结在配置文件中配置多数据源,后来了解到QueryDsl需要配置数据源SqlFactory,一下子思路就打开了,现在写完发现QueryDsl还是简单方便的,SpringBoot集成的东西还是非常多的,学习的路还是非常漫长的,加油!!