zoukankan      html  css  js  c++  java
  • quartz储存方式之JDBC JobStoreTX

    这篇单单记录一下个人配置使用quartz的JDBC JobStoreTX的过程以及其中遇到的问题,这里的quartz是version2.2.1,数据库使用的MySQL

    JDBCJobStore储存是速度比较慢的,但是也不至于很坏,通过JDBCJobStore储存于数据库的方式适用于Oracle,PostgreSQL, mysql, MS SQLServer, HSQLDB, DB2等数据库。

     

    1) 建表

    在下载的文件的docs/dbTables目录下有对应建表语句,如果没有对应于应用的就自己改动来适应。这些个表都有"QRTZ"前缀,可以作为区别于别的命名。

     

    2) 选定事务

    如果你不需要绑定其他事务处理,你可以选择quartz的事务,其通过JobStoreTX来管理,这也是常用的选择,当然如果你要和你的应用容器一起管理,那你可以使用quartz的

    JobStoreCMT,quartz通过JobStoreCMT来的使用来让你的应用容器管理quartz的事务。

     

    3) 创建数据源

    一个是提供一个connection,让quartz可以连接到数据库,另一个是提供的JNDI的方式,让quartz可以从所在容器中获取到。

    使用JDBC连接方式(假设你使用的是StdSchedulerFactory):

     

    首先:
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
    或者
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT

     

    这里当然选择JobStoreTX。


    其次:
    选定JDBC代理类,quartz里提供了StdJDBCDelegate,如果这个不能正常工作的,你可以选用其他代理类(在org.quar.impl.jdbcjobstore package或者其子包中可以找到),包括DB2v6Delegate (for DB2 version 6 and earlier), HSQLDBDelegate (for HSQLDB),MSSQLDelegate (for Microsoft SQLServer), PostgreSQLDelegate (for PostgreSQL),
    WeblogicDelegate (for using JDBC drivers made by WebLogic), OracleDelegate (for using oracle)等等。
    并这样配置:
    org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate


    第三:
    指定前缀
    org.quartz.jobStore.tablePrefix = QRTZ_


    第四:
    指定数据源名称:
    org.quartz.jobStore.dataSource = myDS


    第五:定义ConnectionProvider的实现类

    这里我找了一下,quartz提供了一个org.quartz.utils.PoolingConnectionProvider,于是,我就有了如下配置:

    org.quartz.dataSource.myDS.connectionProvider.class:org.quartz.utils.PoolingConnectionProvider


    第六:配置数据源属性

    org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver
    org.quartz.dataSource.myDS.url: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8
    org.quartz.dataSource.myDS.user: root
    org.quartz.dataSource.myDS.password: root
    org.quartz.dataSource.myDS.maxConnections = 30

    完事,使用最简单的一个例子来跑跑,可是报错了……

    Caused by: Java.lang.InstantiationException: org.quartz.utils.PoolingConnectionProvider
    at java.lang.Class.newInstance(Unknown Source)
    at org.quartz.impl.StdSchedulerFactory.instantiate(StdSchedulerFactory.java:936)
    ... 3 more

    跟了一下源码得到详细一点的原因:

                    ConnectionProvider cp = null;
                    try {
                        cp = (ConnectionProvider) loadHelper.loadClass(cpClass).newInstance();
                    } catch (Exception e) {
                        initException = new SchedulerException("ConnectionProvider class '" + cpClass
                                + "' could not be instantiated.", e);
                        throw initException;
                    }

    红色那行报的:

    org.eclipse.debug.core.DebugException: com.sun.jdi.ClassNotLoadedException: Type has not been loaded occurred while retrieving component type of array.

    百度了一把,没什么收获,看看文档,只说定义自己的这个类,但是为啥,也没有代码,为什么不告诉直接用上述的那个provider呢?

    直接测试一下loadclass("org.quartz.utils.PoolingConnectionProvider");是没有问题的,那就是newInstance();的时候有问题咯。靠谱的还是JDK文档,立马去看一下,果然有收获:创建此Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。如果该类尚未初始化,则初始化这个类。 

    如同空参数……

    肯定是那个provider没有提供无参构造……再去看看呢,果然没有,好吧,我承认我懒了那么一丢丢。

    那我再找找有没有其他的用于设置这个的吧,居然没有找到(估计没有找仔细),还是得定义一个自己的provider,没事,就参考这个provider,还是用C3P0来定义呗。

    定义好后,来试试,果然顶用。以下是我的可运行代码:

    quartz.properties

     

    [plain] view plain copy
     
    1. # Default Properties file for use by StdSchedulerFactory  
    2. # to create a Quartz Scheduler Instance, if a different  
    3. # properties file is not explicitly specified.  
    4. #  
    5.   
    6. org.quartz.scheduler.instanceName: DefaultQuartzScheduler  
    7. org.quartz.scheduler.rmi.export: false  
    8. org.quartz.scheduler.rmi.proxy: false  
    9. org.quartz.scheduler.wrapJobExecutionInUserTransaction: false  
    10.   
    11. org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool  
    12. org.quartz.threadPool.threadCount: 10  
    13. org.quartz.threadPool.threadPriority: 5  
    14. org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: false  
    15.   
    16. org.quartz.jobStore.misfireThreshold: 60000  
    17.   
    18. org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX  
    19. org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  
    20. org.quartz.jobStore.tablePrefix: QRTZ_  
    21. org.quartz.jobStore.dataSource: myDS  
    22.   
    23. org.quartz.dataSource.myDS.connectionProvider.class: org.quartz.examples.example17.MyPoolingconnectionProvider  
    24. org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver  
    25. org.quartz.dataSource.myDS.url: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8  
    26. org.quartz.dataSource.myDS.user: root  
    27. org.quartz.dataSource.myDS.password: root  
    28. org.quartz.dataSource.myDS.maxConnections: 30  


    MyPoolingconnectionProvider.java

     

    [java] view plain copy
     
    1. package org.quartz.examples.example17;  
    2.   
    3. import java.beans.PropertyVetoException;  
    4. import java.sql.Connection;  
    5. import java.sql.SQLException;  
    6.   
    7. import org.quartz.SchedulerException;  
    8. import org.quartz.utils.ConnectionProvider;  
    9.   
    10. import com.mchange.v2.c3p0.ComboPooledDataSource;  
    11.   
    12. /** 
    13.  *  
    14.  * @author wz 
    15.  * 
    16.  */  
    17. public class MyPoolingconnectionProvider implements ConnectionProvider {  
    18.   
    19.     /** Default maximum number of database connections in the pool. */  
    20.     public static final int DEFAULT_DB_MAX_CONNECTIONS = 10;  
    21.   
    22.     /** Default maximum number of database connections in the pool. */  
    23.     public static final int DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION = 120;  
    24.   
    25.     private String driver;  
    26.     private String url;  
    27.     private String user;  
    28.     private String password;  
    29.     private int maxConnections;  
    30.     private int maxCachedStatementsPerConnection;  
    31.     private int maxIdleSeconds;  
    32.     private String validationQuery;  
    33.     private int idleConnectionValidationSeconds;  
    34.     private boolean validateOnCheckout;  
    35.     private String discardIdleConnectionsSeconds;  
    36.   
    37.     private ComboPooledDataSource datasource;  
    38.   
    39.     /** 
    40.      * 无参构造,必须要有[没有其他构造的话也可以不写] 
    41.      */  
    42.     public MyPoolingconnectionProvider() {  
    43.   
    44.     }  
    45.   
    46.     public Connection getConnection() throws SQLException {  
    47.         return datasource.getConnection();  
    48.     }  
    49.   
    50.     public void shutdown() throws SQLException {  
    51.         datasource.close();  
    52.   
    53.     }  
    54.   
    55.     /** 
    56.      * 初始化方法,应该在调用其setter后调用 
    57.      */  
    58.     public void initialize() throws SQLException {  
    59.         if (this.url == null) {  
    60.             throw new SQLException("DBPool could not be created: DB URL cannot be null");  
    61.         }  
    62.   
    63.         if (this.driver == null) {  
    64.             throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");  
    65.         }  
    66.   
    67.         if (this.maxConnections < 0) {  
    68.             throw new SQLException("DBPool maxConnectins could not be created: Max connections must be greater than zero!");  
    69.         }  
    70.   
    71.         datasource = new ComboPooledDataSource();  
    72.         try {  
    73.             datasource.setDriverClass(this.driver);  
    74.         } catch (PropertyVetoException e) {  
    75.             try {  
    76.                 throw new SchedulerException("Problem setting driver class name on datasource: " + e.getMessage(), e);  
    77.             } catch (SchedulerException e1) {  
    78.             }  
    79.         }  
    80.         datasource.setJdbcUrl(this.url);  
    81.         datasource.setUser(this.user);  
    82.         datasource.setPassword(this.password);  
    83.         datasource.setMaxPoolSize(this.maxConnections);  
    84.         datasource.setMinPoolSize(1);  
    85.         datasource.setMaxIdleTime(maxIdleSeconds);  
    86.         datasource.setMaxStatementsPerConnection(this.maxCachedStatementsPerConnection);  
    87.   
    88.         if (this.validationQuery != null) {  
    89.             datasource.setPreferredTestQuery(this.validationQuery);  
    90.             if (!validateOnCheckout)  
    91.                 datasource.setTestConnectionOnCheckin(true);  
    92.             else  
    93.                 datasource.setTestConnectionOnCheckout(true);  
    94.             datasource.setIdleConnectionTestPeriod(this.idleConnectionValidationSeconds);  
    95.         }  
    96.     }  
    97.   
    98.     /*------------------------------------------------- 
    99.      *  
    100.      * setters 如果有必要,你可以添加一些getter 
    101.      * ------------------------------------------------ 
    102.      */  
    103.     public void setDriver(String driver) {  
    104.         this.driver = driver;  
    105.     }  
    106.   
    107.     public void setUrl(String url) {  
    108.         this.url = url;  
    109.     }  
    110.   
    111.     public void setUser(String user) {  
    112.         this.user = user;  
    113.     }  
    114.   
    115.     public void setPassword(String password) {  
    116.         this.password = password;  
    117.     }  
    118.   
    119.     public void setMaxConnections(int maxConnections) {  
    120.         this.maxConnections = maxConnections;  
    121.     }  
    122.   
    123.     public void setMaxCachedStatementsPerConnection(int maxCachedStatementsPerConnection) {  
    124.         this.maxCachedStatementsPerConnection = maxCachedStatementsPerConnection;  
    125.     }  
    126.   
    127.     public void setMaxIdleSeconds(int maxIdleSeconds) {  
    128.         this.maxIdleSeconds = maxIdleSeconds;  
    129.     }  
    130.   
    131.     public void setValidationQuery(String validationQuery) {  
    132.         this.validationQuery = validationQuery;  
    133.     }  
    134.   
    135.     public void setIdleConnectionValidationSeconds(int idleConnectionValidationSeconds) {  
    136.         this.idleConnectionValidationSeconds = idleConnectionValidationSeconds;  
    137.     }  
    138.   
    139.     public void setValidateOnCheckout(boolean validateOnCheckout) {  
    140.         this.validateOnCheckout = validateOnCheckout;  
    141.     }  
    142.   
    143.     public void setDiscardIdleConnectionsSeconds(String discardIdleConnectionsSeconds) {  
    144.         this.discardIdleConnectionsSeconds = discardIdleConnectionsSeconds;  
    145.     }  
    146.   
    147.     public void setDatasource(ComboPooledDataSource datasource) {  
    148.         this.datasource = datasource;  
    149.     }  
    150.   
    151.     protected ComboPooledDataSource getDataSource() {  
    152.         return datasource;  
    153.     }  
    154. }  


    SimpleExample.java

     

    [java] view plain copy
     
    1. package org.quartz.examples.example17;  
    2.   
    3. import java.util.Date;  
    4.   
    5. import org.quartz.DateBuilder;  
    6. import org.quartz.JobBuilder;  
    7. import org.quartz.JobDetail;  
    8. import org.quartz.Scheduler;  
    9. import org.quartz.SchedulerFactory;  
    10. import org.quartz.TriggerBuilder;  
    11. import org.quartz.impl.StdSchedulerFactory;  
    12. import org.quartz.impl.triggers.SimpleTriggerImpl;  
    13. import org.slf4j.Logger;  
    14. import org.slf4j.LoggerFactory;  
    15.   
    16. public class SimpleExample  
    17. {  
    18.   public void run()  
    19.     throws Exception  
    20.   {  
    21.     Logger log = LoggerFactory.getLogger(SimpleExample.class);  
    22.   
    23.     log.info("------- Initializing ----------------------");  
    24.     //通过调度器工厂获取调度器,初始化工程时须指定其使用我们自己的配置文件  
    25.     SchedulerFactory sf = new StdSchedulerFactory("org/quartz/examples/example17/quartz.properties");  
    26.     Scheduler sched = sf.getScheduler();  
    27.       
    28.     //这儿clear一下,因为使用数据库储存方式时,shutdown的时候没有清除,第二次运行会报Job is already exist  
    29.     sched.clear();    
    30.   
    31.     log.info("------- Initialization Complete -----------");  
    32.   
    33.     Date runTime = DateBuilder.evenMinuteDate(new Date());  
    34.   
    35.     log.info("------- Scheduling Job  -------------------");  
    36.       
    37.     //创建任务详情  
    38.     JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();  
    39.     //创建触发器  
    40.     SimpleTriggerImpl trigger = (SimpleTriggerImpl)TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(new Date()).build();  
    41.     trigger.setRepeatCount(5);  
    42.     trigger.setRepeatInterval(3000);  
    43.     log.info("------- Starttime =  "+trigger.getStartTime()+" -----------------");  
    44.       
    45.     //调度器、触发器、任务,三者关联  
    46.     sched.scheduleJob(job, trigger);  
    47.     log.info(job.getKey() + " will run at: " + runTime);  
    48.     //调度启动  
    49.     sched.start();  
    50.     log.info("------- Started Scheduler -----------------");  
    51.   
    52.     log.info("------- Waiting 1 minute... -------------");  
    53.     try  
    54.     {  
    55.       Thread.sleep(60000L);  
    56.     }  
    57.     catch (Exception e)  
    58.     {  
    59.     }  
    60.   
    61.     log.info("------- Shutting Down ---------------------");  
    62.     //调度关闭  
    63.     sched.shutdown(true);  
    64.     log.info("------- Shutdown Complete -----------------");  
    65.   }  
    66.   
    67.   public static void main(String[] args) throws Exception  
    68.   {  
    69.     SimpleExample example = new SimpleExample();  
    70.     example.run();  
    71.   }  
    72. }  


    当然,运行example之前,得先添加mysql的driver的包,然后在mysql里建立一个叫“quartz”的database,并将docs/dbTables下的tables_mysql.sql脚本运行一下以建表。

     

     

    注意:

    1) org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX,这个配置在这儿当然是用这个,

    而org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate则根据你的数据,通常使用当前这个,如果这个不适用就去quartz里org.quar.impl.jdbcjobstore包或其子包下找找,如还是未能满足需求,就自己实现一个。

    2) org.quartz.jobStore.tablePrefix: QRTZ_,这个是quartz默认的,tables_mysql.sql以及一些其他操作(比如clear等)的代码都这样写了,所以就不要去修改了。

    3) org.quartz.jobStore.dataSource: myDS这个的“键”必须是org.quartz.jobStore.dataSource,而“值”随你取,但必须有。

    4) dataSource的属性配置,如下几个(可以自己添加其他的对应修改provider):

     

    [html] view plain copy
     
    1. org.quartz.dataSource.myDS.connectionProvider.class: org.quartz.examples.example17.MyPoolingconnectionProvider  
    2. org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver  
    3. org.quartz.dataSource.myDS.url: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8  
    4. org.quartz.dataSource.myDS.user: root  
    5. org.quartz.dataSource.myDS.password: root  
    6. org.quartz.dataSource.myDS.maxConnections: 30  

    它们的“键”必须是

    [html] view plain copy
     
    1. org.quartz.dataSource."+yourdatasourcename+"."+yourProvider#datamembername  

    原因如下:

     

     

    [java] view plain copy
     
      1. String[] dsNames = cfg.getPropertyGroups(PROP_DATASOURCE_PREFIX);  
      2.         for (int i = 0; i < dsNames.length; i++) {  
      3.             PropertiesParser pp = new PropertiesParser(cfg.getPropertyGroup(  
      4.                     PROP_DATASOURCE_PREFIX + "." + dsNames[i], true));  
      5.   
      6.             String cpClass = pp.getStringProperty(PROP_CONNECTION_PROVIDER_CLASS, null);  
      7.   
      8.             // custom connectionProvider...  
      9.             if(cpClass != null) {  
      10.                 ConnectionProvider cp = null;  
      11.                 try {  
      12.                     cp = (ConnectionProvider) loadHelper.loadClass(cpClass).newInstance();  
      13.                 } catch (Exception e) {  
      14.                     initException = new SchedulerException("ConnectionProvider class '" + cpClass  
      15.                             + "' could not be instantiated.", e);  
      16.                     throw initException;  
      17.                 }  
      18.   
      19.                 try {  
      20.                     // remove the class name, so it isn't attempted to be set  
      21.                     pp.getUnderlyingProperties().remove(  
      22.                             PROP_CONNECTION_PROVIDER_CLASS);  
      23.   
      24.                     setBeanProps(cp, pp.getUnderlyingProperties());  
      25.                     cp.initialize();  
      26.                 } catch (Exception e) {  
      27.                     initException = new SchedulerException("ConnectionProvider class '" + cpClass  
      28.                             + "' props could not be configured.", e);  
      29.                     throw initException;  
      30.                 }  
      31.   
      32.                 dbMgr = DBConnectionManager.getInstance();  
      33.                 dbMgr.addConnectionProvider(dsNames[i], cp);  
      34.             }   
  • 相关阅读:
    C#调用WebService实现天气预报
    火狐完整版下载地址
    Unity3D 中 2D_Toolkit插件下载 和 导入方法
    给大家分享个 网站头像上传的 插件
    JQuery工具方法,实例方法
    ireport5.6.0 win10打不开
    JFreeChart 零散
    JS 类继承 原型继承
    技术电子书下载网址
    正则 变量替换
  • 原文地址:https://www.cnblogs.com/cnblog-long/p/7278969.html
Copyright © 2011-2022 走看看