依赖包
- springboot 是2.X版本,quartz已经在starter之中
- maven依赖包如下:
org.springframework.boot
spring-boot-starter-data-jpa
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-quartz
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
配置文件
- yml配置文件如下:
server:
port: 8014
spring:
application:
name: r-project-quartz
datasource:
primary:
jdbc-url: jdbc:mysql://localhost:3307/JLCredit #连接user数据库
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
quartz:
jdbc-url: jdbc:mysql://localhost:3307/QUARTZ_TABLE #连接user数据库
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
hibernate:
naming:
#命名规则设置
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
quartz:
#持久化方式,将定时任务信息储存到数据库
#持久化到数据库之后,暂定/启动等定时任务状态也会持久化
job-store-type: jdbc
#初始化表结构
jdbc:
initialize-schema: never
#由配置创建的作业是否覆盖从持久性作业存储中读取的作业
overwrite-existing-jobs: false
#相关属性配置
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
# 数据源名称
dataSource: quartzDataSource
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 1000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
- 在此处配置了两个mysql数据库,其中primary为默认数据库
- jpa.hibernate.naming.physical-strategy是数据库命名规则。由于数据库中数据库名称和字段都是大写,而jpa默认字段都会转为小写,于是改变命名规则,使得其与当前书写方式完全一致
- jobStore.dataSource是指quartz持久化所使用的数据库的来源,会带在代码中用@QuartzDataSource来注明
- quartz. job-store-type指的是定时任务的持久化,当服务关闭再开启的时候,能够读取任务的状态,例如暂停或者开启;若是配置为memory则无需配置持久化数据库了
- quartz.jdbc.initialize-schema据说能自动建表,但是我没成功过,建表所需的各版本sql语句参考:https://github.com/quartz-scheduler/quartz/tree/9f9e400733f51f7cb658e3319fc2c140ab8af938/quartz-core/src/main/resources/org/quartz/impl/jdbcjobstore(基本上度娘找出来的都是mysql的写法,一大堆写各版本的标题党,当真浪费时间)
多数据源设置
- 数据源总的配置:
@Configuration
public class DataSourceConfig {
@Primary //主数据库
@Bean(name = "primarySource")//将该对象放入spring容器
@Qualifier("primarySource")//寻找spring容器该名字的对象
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primarySource() {
return DataSourceBuilder.create().build();
}
@QuartzDataSource
@Bean(name = "quartzSource")
@Qualifier("quartzSource")
@ConfigurationProperties(prefix = "spring.datasource.quartz")
public DataSource quartzSource() {
return DataSourceBuilder.create().build();
}
}
- @Primary 注解在主数据库上
- @QuartzDataSource注解在quartz持久化数据库上
- @ConfigurationProperties对应配置文件的内容,不能写错
- 各个数据库的配置:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager",
basePackages = {"com.ladyishenlong.rprojectquartz.jpa.primary"}) //设置Repository所在位置
public class PrimaryConfig {
@Autowired
private JpaProperties jpaProperties;
@Resource
private HibernateProperties hibernateProperties;
@Autowired
@Qualifier("primarySource")
private DataSource primaryDataSource;
@Primary
@Bean(name = "primaryEntityManager")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return Objects.requireNonNull(primaryEntityManagerFactory(builder).getObject()).createEntityManager();
}
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(primaryDataSource)
.properties(hibernateProperties.determineHibernateProperties(
jpaProperties.getProperties(), new HibernateSettings()))
.packages("com.ladyishenlong.rprojectquartz.model.primary") //设置实体类所在位置
.persistenceUnit("primaryPersistenceUnit")
.build();
}
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(primaryEntityManagerFactory(builder).getObject());
}
}
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "quartzEntityManagerFactory",
transactionManagerRef = "quartzTransactionManager",
basePackages = {"com.ladyishenlong.rprojectquartz.jpa.quartz"}) //设置Repository所在位置
public class QuartzConfig {
@Autowired
private JpaProperties jpaProperties;
@Resource
private HibernateProperties hibernateProperties;
@Autowired
@Qualifier("quartzSource")
private DataSource quartzDataSource;
@Bean(name = "quartzEntityManager")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return Objects.requireNonNull(quartzEntityManagerFactory(builder).getObject()).createEntityManager();
}
@Bean(name = "quartzEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean quartzEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(quartzDataSource)
.properties(hibernateProperties.determineHibernateProperties(
jpaProperties.getProperties(), new HibernateSettings()))
.packages("com.ladyishenlong.rprojectquartz.model.quartz") //设置实体类所在位置
.persistenceUnit("quartzPersistenceUnit")
.build();
}
@Bean(name = "quartzTransactionManager")
public PlatformTransactionManager quartzTransactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(quartzEntityManagerFactory(builder).getObject());
}
}
- @Primary只需要在主数据库的文件中添加
- basePackages里面写的是继承了JpaRepository类的文件的位置;entityManagerFactoryRef与transactionManagerRef是自定义的
- packages里面写的是该对应数据库的实体类的位置
- @Qualifier与DataSourceConfig文件之中的@Qualifier对应
- 至此,jpa的多数据源就配置完毕,其中一个是主要数据库,另一个是用来做quartz的持久化
Quartz定时任务
- 注册定时任务
@Configuration
public class QuartzTaskConfig {
@Bean
public JobDetail uploadTaskDetail() {
return JobBuilder
.newJob(MyJob.class).withIdentity("MyJob","Jobs")
.storeDurably()
.build();
}
//指定具体的定时任务类
@Bean
public JobDetail uploadTaskDetail2() {
return JobBuilder
.newJob(MyJob2.class).withIdentity("MyJob2","Jobs")
.storeDurably()
.build();
}
@Bean
public Trigger uploadTaskTrigger() {
//每隔5秒执行一次
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule("*/5 * * * * ?");
// 返回任务触发器
return TriggerBuilder
.newTrigger()
.forJob(uploadTaskDetail())
.withIdentity("MyJob")
.withSchedule(scheduleBuilder)
.build();
}
@Bean
public Trigger uploadTaskTrigger2() {
//每隔5秒执行一次
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule("*/5 * * * * ?");
// 返回任务触发器
return TriggerBuilder
.newTrigger()
.forJob(uploadTaskDetail2())
.withIdentity("MyJob2")
.withSchedule(scheduleBuilder)
.build();
}
}
- 这里注册两个简单的定时任务,都是每隔5s执行一次
@Slf4j
public class MyJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("---- 这里是执行定时任务的逻辑的地方 ----");
}
}
- 定时任务编写方法如上所示,executeInternal方法之中编写具体的业务逻辑
- quartz与springboot自带的定时任务不同的是,它是异步的且是可以控制的,在这里简单写了下暂停的重新开始的方法,可以用在controller用来控制定时任务
@Service
public class JobAndTriggerService {
@Autowired
private Scheduler scheduler;
public void pauseJob(String jobClassName, String jobGroupName) throws SchedulerException {
scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
}
public void resumeJob(String jobClassName, String jobGroupName) throws SchedulerException {
scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
}
}
- 其中jobClassName以及jobGroupName是注册时候定义的,最好两个都要定义
- 如果用jdbc持久化,且用sql已经在数据库中建表,服务第一次起来以后,数据库中会自动生成这些定时任务的信息,可以连接数据库查看
jpa的entityManager写法
- jpa能够自动生成sql,但是有些情况需要自己写sql,于是需要使用entityManager
@Service
public class ArticleDao {
/**
* 多数据源配置时候,指定数据源
*/
// @PersistenceContext //无多数据源时候
@Autowired
@Qualifier("primaryEntityManagerFactory")
private EntityManager entityManager;
public Object test() {
String sql = "select * from article";
List articleIndexModels = entityManager
//将查询结果赋值给实体类
.createNativeQuery(sql, ArticleTable.class)
.getResultList();
return articleIndexModels;
}
/**
* 改动数据库操作必须放在事务之中
* 增删改 操作相似
* @return
*/
@Transactional
public Object test2() {
String sql = "insert into article(id, content) values ('12334','搞事情')";
entityManager
.createNativeQuery(sql)
.executeUpdate();
return "执行成功";
}
}
- 如果是单数据源,EntityManager上使用@PersistenceContext注解,多数据源的情况下,需要使用@Autowired与 @Qualifier注解,其中@Qualifier内的之要和entityManagerFactoryRef里面的值一致保证连接的数据库正确
- 增删改语句使用大致相同,如上代码所示
项目git:https://github.com/ladyishenlong/project-r