From b03caffc42161670903a5e078c822a02030f0d9e Mon Sep 17 00:00:00 2001 From: dsyer Date: Tue, 28 Aug 2007 20:35:02 +0000 Subject: [PATCH] Add tablePrefix feature to SqlStepDao. REOPENED - issue BATCH-93: Need to be able to configure table names! http://opensource.atlassian.com/projects/spring/browse/BATCH-93 --- .../execution/repository/dao/SqlJobDao.java | 4 +- .../execution/repository/dao/SqlStepDao.java | 53 +++-- .../repository/dao/BaseStepDaoTests.java | 206 ++++++++++++++++++ .../repository/dao/HibernateStepDaoTests.java | 2 +- 4 files changed, 245 insertions(+), 20 deletions(-) create mode 100644 execution/src/test/java/org/springframework/batch/execution/repository/dao/BaseStepDaoTests.java diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java index 82017e3ca..cde82179b 100644 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java @@ -53,7 +53,7 @@ public class SqlJobDao implements JobDao, InitializingBean { */ public static final String DEFAULT_TABLE_PREFIX = "BATCH_"; - private static String tablePrefix = DEFAULT_TABLE_PREFIX; + private String tablePrefix = DEFAULT_TABLE_PREFIX; // Job SQL statements private static final String CREATE_JOB = "INSERT into %PREFIX%JOB(ID, JOB_NAME, JOB_STREAM, SCHEDULE_DATE, JOB_RUN)" @@ -94,7 +94,7 @@ public class SqlJobDao implements JobDao, InitializingBean { * the tablePrefix to set */ public void setTablePrefix(String tablePrefix) { - SqlJobDao.tablePrefix = tablePrefix; + this.tablePrefix = tablePrefix; } /** diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java index 188e8a361..d11e808e0 100644 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java @@ -34,6 +34,7 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Sql implementation of StepDao. Uses Sequences (via Spring's @@ -54,27 +55,27 @@ import org.springframework.util.Assert; public class SqlStepDao implements StepDao, InitializingBean { // Step SQL statements - private static final String FIND_STEPS = "SELECT ID, STEP_NAME, STATUS, RESTART_DATA from BATCH_STEP where JOB_ID = ?"; + private static final String FIND_STEPS = "SELECT ID, STEP_NAME, STATUS, RESTART_DATA from %PREFIX%STEP where JOB_ID = ?"; - private static final String FIND_STEP = "SELECT ID, STATUS, RESTART_DATA from BATCH_STEP where JOB_ID = ? " + private static final String FIND_STEP = "SELECT ID, STATUS, RESTART_DATA from %PREFIX%STEP where JOB_ID = ? " + "and STEP_NAME = ?"; - private static final String CREATE_STEP = "INSERT into BATCH_STEP(ID, JOB_ID, STEP_NAME) values (?, ?, ?)"; + private static final String CREATE_STEP = "INSERT into %PREFIX%STEP(ID, JOB_ID, STEP_NAME) values (?, ?, ?)"; - private static final String UPDATE_STEP = "UPDATE BATCH_STEP set STATUS = ?, RESTART_DATA = ? where ID = ?"; + private static final String UPDATE_STEP = "UPDATE %PREFIX%STEP set STATUS = ?, RESTART_DATA = ? where ID = ?"; // StepExecution statements - private static final String SAVE_STEP_EXECUTION = "INSERT into BATCH_STEP_EXECUTION(ID, VERSION, STEP_ID, JOB_EXECUTION_ID, START_TIME, " + private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(ID, VERSION, STEP_ID, JOB_EXECUTION_ID, START_TIME, " + "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, TASK_STATISTICS, EXIT_CODE) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - private static final String UPDATE_STEP_EXECUTION = "UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, " + private static final String UPDATE_STEP_EXECUTION = "UPDATE %PREFIX%STEP_EXECUTION set START_TIME = ?, END_TIME = ?, " + "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, TASK_STATISTICS = ?, EXIT_CODE = ? where ID = ?"; - private static final String GET_STEP_EXECUTION_COUNT = "SELECT count(ID) from BATCH_STEP_EXECUTION where " + private static final String GET_STEP_EXECUTION_COUNT = "SELECT count(ID) from %PREFIX%STEP_EXECUTION where " + "STEP_ID = ?"; private static final String FIND_STEP_EXECUTIONS = "SELECT ID, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT," - + " TASK_COUNT, TASK_STATISTICS, EXIT_CODE from BATCH_STEP_EXECUTION where STEP_ID = ?"; + + " TASK_COUNT, TASK_STATISTICS, EXIT_CODE from %PREFIX%STEP_EXECUTION where STEP_ID = ?"; private JdbcTemplate jdbcTemplate; @@ -82,6 +83,20 @@ public class SqlStepDao implements StepDao, InitializingBean { private DataFieldMaxValueIncrementer stepExecutionIncrementer; + private String tablePrefix = SqlJobDao.DEFAULT_TABLE_PREFIX; + + /** + * Public setter for the table prefix property. This will be prefixed to all + * the table names before queries are executed. Defaults to + * {@value #DEFAULT_TABLE_PREFIX}. + * + * @param tablePrefix + * the tablePrefix to set + */ + public void setTablePrefix(String tablePrefix) { + this.tablePrefix = tablePrefix; + } + /** * Find one step for given job and stepName. A RowMapper is used to map each * row returned to a step object. If none are found, the list will be empty @@ -113,7 +128,7 @@ public class SqlStepDao implements StepDao, InitializingBean { }; - List steps = jdbcTemplate.query(FIND_STEP, parameters, rowMapper); + List steps = jdbcTemplate.query(getQuery(FIND_STEP), parameters, rowMapper); if (steps.size() == 0) { // No step found @@ -138,7 +153,7 @@ public class SqlStepDao implements StepDao, InitializingBean { * @see StepDao#findSteps(Long) * * Sql implementation which uses a RowMapper to populate a list of all rows - * in the BATCH_STEP table with the same JOB_ID. + * in the step table with the same JOB_ID. * * @throws IllegalArgumentException if jobId is null. */ @@ -162,7 +177,7 @@ public class SqlStepDao implements StepDao, InitializingBean { } }; - return jdbcTemplate.query(FIND_STEPS, parameters, rowMapper); + return jdbcTemplate.query(getQuery(FIND_STEPS), parameters, rowMapper); } /** @@ -180,7 +195,7 @@ public class SqlStepDao implements StepDao, InitializingBean { Long stepId = new Long(stepIncrementer.nextLongValue()); Object[] parameters = new Object[] { stepId, job.getId(), stepName }; - jdbcTemplate.update(CREATE_STEP, parameters); + jdbcTemplate.update(getQuery(CREATE_STEP), parameters); StepInstance step = new StepInstance(stepId); step.setJob(job); @@ -209,7 +224,7 @@ public class SqlStepDao implements StepDao, InitializingBean { step.getId() }; - jdbcTemplate.update(UPDATE_STEP, parameters); + jdbcTemplate.update(getQuery(UPDATE_STEP), parameters); } /** @@ -228,7 +243,7 @@ public class SqlStepDao implements StepDao, InitializingBean { stepExecution.getStartTime(), stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getTaskCount(), PropertiesConverter.propertiesToString(stepExecution.getStatistics()), stepExecution.getExitCode() }; - jdbcTemplate.update(SAVE_STEP_EXECUTION, parameters); + jdbcTemplate.update(getQuery(SAVE_STEP_EXECUTION), parameters); } @@ -254,7 +269,7 @@ public class SqlStepDao implements StepDao, InitializingBean { stepExecution.getTaskCount(), PropertiesConverter.propertiesToString(stepExecution.getStatistics()), stepExecution.getExitCode(), stepExecution.getId() }; - jdbcTemplate.update(UPDATE_STEP_EXECUTION, parameters); + jdbcTemplate.update(getQuery(UPDATE_STEP_EXECUTION), parameters); } @@ -262,7 +277,7 @@ public class SqlStepDao implements StepDao, InitializingBean { Object[] parameters = new Object[] { stepId }; - return jdbcTemplate.queryForInt(GET_STEP_EXECUTION_COUNT, parameters); + return jdbcTemplate.queryForInt(getQuery(GET_STEP_EXECUTION_COUNT), parameters); } /** @@ -297,7 +312,7 @@ public class SqlStepDao implements StepDao, InitializingBean { } }; - return jdbcTemplate.query(FIND_STEP_EXECUTIONS, new Object[] { stepId }, rowMapper); + return jdbcTemplate.query(getQuery(FIND_STEP_EXECUTIONS), new Object[] { stepId }, rowMapper); } @@ -319,6 +334,10 @@ public class SqlStepDao implements StepDao, InitializingBean { Assert.notNull(stepExecutionIncrementer, "StepExecutionIncrementer canot be null."); } + private String getQuery(String base) { + return StringUtils.replace(base, "%PREFIX%", tablePrefix); + } + /* * Validate StepExecution. At a minimum, JobId, StartTime, and * Status cannot be null. EndTime can be null for an unfinished job. diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/BaseStepDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/BaseStepDaoTests.java new file mode 100644 index 000000000..d91d6af65 --- /dev/null +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/BaseStepDaoTests.java @@ -0,0 +1,206 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.execution.repository.dao; + +import java.sql.Timestamp; +import java.util.List; +import java.util.Properties; + +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.core.domain.StepInstance; +import org.springframework.batch.core.runtime.JobIdentifier; +import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; +import org.springframework.batch.restart.GenericRestartData; +import org.springframework.batch.restart.RestartData; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; +import org.springframework.util.ClassUtils; + +/** + * Test for StepDao. Because it is very reasonable to assume that there is a + * foreign key constraint on the JobId of a step, the JobDao is used to create + * jobs, to have an id for creating steps. + * + * @author Lucas Ward + */ +public class BaseStepDaoTests extends AbstractTransactionalDataSourceSpringContextTests { + + protected JobDao jobDao; + + protected StepDao stepDao; + + protected JobInstance job; + + protected StepInstance step1; + + protected StepInstance step2; + + protected StepExecution stepExecution; + + public void setJobDao(JobDao jobDao) { + this.jobDao = jobDao; + } + + public void setStepDao(StepDao stepDao) { + this.stepDao = stepDao; + } + + /* + * (non-Javadoc) + * @see org.springframework.test.AbstractSingleSpringContextTests#getConfigLocations() + */ + protected String[] getConfigLocations() { + return new String[] { ClassUtils.addResourcePathToPackagePath(getClass(), "sql-dao-test.xml") }; + } + + /* + * (non-Javadoc) + * @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpInTransaction() + */ + protected void onSetUpInTransaction() throws Exception { + JobIdentifier jobIdentifier = new ScheduledJobIdentifier("TestJob"); + job = jobDao.createJob(jobIdentifier); + step1 = stepDao.createStep(job, "TestStep1"); + step2 = stepDao.createStep(job, "TestStep2"); + + stepExecution = new StepExecution(step1.getId(), new Long(23)); + stepExecution.setStatus(BatchStatus.STARTED); + stepExecution.setStartTime(new Timestamp(System.currentTimeMillis())); + stepDao.save(stepExecution); + } + + public void testVersionIsNotNullForStep() throws Exception { + int version = jdbcTemplate.queryForInt("select version from BATCH_STEP where ID="+step1.getId()); + assertEquals(0, version); + } + + public void testVersionIsNotNullForStepExecution() throws Exception { + int version = jdbcTemplate.queryForInt("select version from BATCH_STEP_EXECUTION where ID="+stepExecution.getId()); + assertEquals(0, version); + } + + public void testFindStepNull(){ + + StepInstance step = stepDao.findStep(job, "UnSavedStep"); + assertNull(step); + } + + public void testFindStep(){ + + StepInstance tempStep = stepDao.findStep(job, "TestStep1"); + assertEquals(tempStep, step1); + } + + public void testFindSteps(){ + + List steps = stepDao.findSteps(job.getId()); + assertEquals(steps.size(), 2); + assertTrue(steps.contains(step1)); + assertTrue(steps.contains(step2)); + } + + public void testFindStepsNotSaved(){ + + //no steps are saved for given id, empty list should be returned + List steps = stepDao.findSteps(new Long(38922)); + assertEquals(steps.size(), 0); + } + + public void testCreateStep(){ + + StepInstance step3 = stepDao.createStep(job, "TestStep3"); + StepInstance tempStep = stepDao.findStep(job, "TestStep3"); + assertEquals(step3, tempStep); + } + + public void testUpdateStepWithoutRestartData(){ + + step1.setStatus(BatchStatus.COMPLETED); + stepDao.update(step1); + StepInstance tempStep = stepDao.findStep(job, step1.getName()); + assertEquals(tempStep, step1); + } + + public void testUpdateStepWithRestartData(){ + + step1.setStatus(BatchStatus.COMPLETED); + Properties data = new Properties(); + data.setProperty("restart.key1", "restartData"); + RestartData restartData = new GenericRestartData(data); + step1.setRestartData(restartData); + stepDao.update(step1); + StepInstance tempStep = stepDao.findStep(job, step1.getName()); + assertEquals(tempStep, step1); + assertEquals(tempStep.getRestartData().getProperties().toString(), + restartData.getProperties().toString()); + } + + public void testSaveStepExecution(){ + + StepExecution execution = new StepExecution(step2.getId(), new Long(10)); + execution.setStatus(BatchStatus.STARTED); + execution.setStartTime(new Timestamp(System.currentTimeMillis())); + Properties statistics = new Properties(); + statistics.setProperty("statistic.key1", "0"); + statistics.setProperty("statistic.key2", "5"); + execution.setStatistics(statistics); + stepDao.save(execution); + List executions = stepDao.findStepExecutions(step2); + assertEquals(1, executions.size()); + StepExecution tempExecution = (StepExecution)executions.get(0); + assertEquals(execution, tempExecution); + assertEquals(execution.getStatistics(), tempExecution.getStatistics()); + } + + public void testUpdateStepExecution(){ + + stepExecution.setStatus(BatchStatus.COMPLETED); + stepExecution.setEndTime(new Timestamp(System.currentTimeMillis())); + stepExecution.setCommitCount(5); + stepExecution.setTaskCount(5); + stepExecution.setStatistics(new Properties()); + stepDao.update(stepExecution); + List executions = stepDao.findStepExecutions(step1); + assertEquals(1, executions.size()); + assertEquals(stepExecution, (StepExecution)executions.get(0)); + } + + public void testUpdateStepExecutionWithNullId(){ + StepExecution stepExecution = new StepExecution(null, null); + try{ + stepDao.update(stepExecution); + fail(); + }catch(IllegalArgumentException ex){ + //expected + } + } + + public void testGetStepExecutionCountForNoExecutions(){ + + int executionCount = stepDao.getStepExecutionCount(step2.getId()); + assertEquals(executionCount, 0); + } + + public void testIncrementStepExecutionCount(){ + + assertEquals(1, stepDao.getStepExecutionCount(step1.getId())); + StepExecution execution = new StepExecution(step1.getId(), new Long(9)); + stepDao.save(execution); + assertEquals(2, stepDao.getStepExecutionCount(step1.getId())); + } +} diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateStepDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateStepDaoTests.java index 264c94723..5d3212524 100644 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateStepDaoTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateStepDaoTests.java @@ -24,7 +24,7 @@ import org.springframework.batch.core.domain.StepInstance; import org.springframework.batch.support.PropertiesConverter; import org.springframework.util.ClassUtils; -public class HibernateStepDaoTests extends SqlStepDaoTests { +public class HibernateStepDaoTests extends BaseStepDaoTests { private SessionFactory sessionFactory;