You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by js...@apache.org on 2006/07/21 16:10:45 UTC
svn commit: r424328 - in
/incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq:
broker/ store/jdbc/
Author: jstrachan
Date: Fri Jul 21 07:10:45 2006
New Revision: 424328
URL: http://svn.apache.org/viewvc?rev=424328&view=rev
Log:
an implementation of an exclusive lock in SQL to ensure that only one JDBC message store is run against a database at once to fix AMQ-831. For documentation on this feature see: http://activemq.org/site/jdbc-master-slave.html
Added:
incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerServiceAware.java (with props)
incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DatabaseLocker.java (with props)
incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DefaultDatabaseLocker.java (with props)
Modified:
incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java
incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java
incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/Statements.java
Modified: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java?rev=424328&r1=424327&r2=424328&view=diff
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java (original)
+++ incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerService.java Fri Jul 21 07:10:45 2006
@@ -558,6 +558,7 @@
public PersistenceAdapter getPersistenceAdapter() throws IOException {
if (persistenceAdapter == null) {
persistenceAdapter = createPersistenceAdapter();
+ configureService(persistenceAdapter);
}
return persistenceAdapter;
}
@@ -771,6 +772,54 @@
getPersistenceAdapter().deleteAllMessages();
}
+ public boolean isDeleteAllMessagesOnStartup() {
+ return deleteAllMessagesOnStartup;
+ }
+
+ /**
+ * Sets whether or not all messages are deleted on startup - mostly only
+ * useful for testing.
+ */
+ public void setDeleteAllMessagesOnStartup(boolean deletePersistentMessagesOnStartup) {
+ this.deleteAllMessagesOnStartup = deletePersistentMessagesOnStartup;
+ }
+
+ public URI getVmConnectorURI() {
+ if (vmConnectorURI == null) {
+ try {
+ vmConnectorURI = new URI("vm://" + getBrokerName());
+ }
+ catch (URISyntaxException e) {
+ }
+ }
+ return vmConnectorURI;
+ }
+
+ public void setVmConnectorURI(URI vmConnectorURI) {
+ this.vmConnectorURI = vmConnectorURI;
+ }
+
+ /**
+ * @return Returns the shutdownOnMasterFailure.
+ */
+ public boolean isShutdownOnMasterFailure(){
+ return shutdownOnMasterFailure;
+ }
+
+ /**
+ * @param shutdownOnMasterFailure The shutdownOnMasterFailure to set.
+ */
+ public void setShutdownOnMasterFailure(boolean shutdownOnMasterFailure){
+ this.shutdownOnMasterFailure=shutdownOnMasterFailure;
+ }
+
+ public boolean isKeepDurableSubsActive() {
+ return keepDurableSubsActive;
+ }
+
+ public void setKeepDurableSubsActive(boolean keepDurableSubsActive) {
+ this.keepDurableSubsActive = keepDurableSubsActive;
+ }
// Implementation methods
// -------------------------------------------------------------------------
/**
@@ -1132,52 +1181,13 @@
connector.start();
}
- public boolean isDeleteAllMessagesOnStartup() {
- return deleteAllMessagesOnStartup;
- }
-
/**
- * Sets whether or not all messages are deleted on startup - mostly only
- * useful for testing.
+ * Perform any custom dependency injection
*/
- public void setDeleteAllMessagesOnStartup(boolean deletePersistentMessagesOnStartup) {
- this.deleteAllMessagesOnStartup = deletePersistentMessagesOnStartup;
- }
-
- public URI getVmConnectorURI() {
- if (vmConnectorURI == null) {
- try {
- vmConnectorURI = new URI("vm://" + getBrokerName());
- }
- catch (URISyntaxException e) {
- }
+ protected void configureService(Object service) {
+ if (service instanceof BrokerServiceAware) {
+ BrokerServiceAware serviceAware = (BrokerServiceAware) service;
+ serviceAware.setBrokerService(this);
}
- return vmConnectorURI;
- }
-
- public void setVmConnectorURI(URI vmConnectorURI) {
- this.vmConnectorURI = vmConnectorURI;
- }
-
- /**
- * @return Returns the shutdownOnMasterFailure.
- */
- public boolean isShutdownOnMasterFailure(){
- return shutdownOnMasterFailure;
- }
-
- /**
- * @param shutdownOnMasterFailure The shutdownOnMasterFailure to set.
- */
- public void setShutdownOnMasterFailure(boolean shutdownOnMasterFailure){
- this.shutdownOnMasterFailure=shutdownOnMasterFailure;
- }
-
- public boolean isKeepDurableSubsActive() {
- return keepDurableSubsActive;
- }
-
- public void setKeepDurableSubsActive(boolean keepDurableSubsActive) {
- this.keepDurableSubsActive = keepDurableSubsActive;
}
}
Added: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerServiceAware.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerServiceAware.java?rev=424328&view=auto
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerServiceAware.java (added)
+++ incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerServiceAware.java Fri Jul 21 07:10:45 2006
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * 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.apache.activemq.broker;
+
+/**
+ * An interface used to represent a component that wants the {@link BrokerService}
+ * to be injected
+ *
+ * @version $Revision: $
+ */
+public interface BrokerServiceAware {
+
+ public void setBrokerService(BrokerService brokerService);
+}
Propchange: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/broker/BrokerServiceAware.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DatabaseLocker.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DatabaseLocker.java?rev=424328&view=auto
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DatabaseLocker.java (added)
+++ incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DatabaseLocker.java Fri Jul 21 07:10:45 2006
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * 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.apache.activemq.store.jdbc;
+
+import org.apache.activemq.Service;
+
+/**
+ * Represents some kind of lock service to ensure that a broker is the only master
+ *
+ * @version $Revision: $
+ */
+public interface DatabaseLocker extends Service {
+
+ /**
+ * Used by a timer to keep alive the lock.
+ * If the method returns false the broker should be terminated
+ */
+ public boolean keepAlive();
+
+}
Propchange: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DatabaseLocker.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DefaultDatabaseLocker.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DefaultDatabaseLocker.java?rev=424328&view=auto
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DefaultDatabaseLocker.java (added)
+++ incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DefaultDatabaseLocker.java Fri Jul 21 07:10:45 2006
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * 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.apache.activemq.store.jdbc;
+
+import org.apache.activemq.Service;
+import org.apache.activemq.broker.BrokerService;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.sql.DataSource;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * Represents an exclusive lock on a database to avoid multiple brokers
+ * running against the same logical database.
+ *
+ * @version $Revision: $
+ */
+public class DefaultDatabaseLocker implements DatabaseLocker {
+ private static final Log log = LogFactory.getLog(DefaultDatabaseLocker.class);
+
+ private final DataSource dataSource;
+ private final Statements statements;
+ private long sleepTime = 1000;
+ private Connection connection;
+
+ public DefaultDatabaseLocker(DataSource dataSource, Statements statements) {
+ this.dataSource = dataSource;
+ this.statements = statements;
+ }
+
+ public void start() throws Exception {
+ log.debug("Attempting to acquire exclusive lock on the database");
+
+ connection = dataSource.getConnection();
+ connection.setAutoCommit(false);
+
+ PreparedStatement statement = connection.prepareStatement(statements.getLockCreateStatement());
+ while (true) {
+ try {
+ boolean answer = statement.execute();
+ if (answer) {
+ break;
+ }
+ }
+ catch (Exception e) {
+ log.error("Failed to acquire lock: " + e, e);
+ }
+ log.info("Sleeping for " + sleepTime + " milli(s) before trying again to get the lock...");
+ Thread.sleep(sleepTime);
+ }
+
+ log.info("Becoming the master on dataSource: " + dataSource);
+ }
+
+ public void stop() throws Exception {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+
+ public boolean keepAlive() {
+ try {
+ PreparedStatement statement = connection.prepareStatement(statements.getLockUpdateStatement());
+ statement.setLong(1, System.currentTimeMillis());
+ int rows = statement.executeUpdate();
+ if (rows == 1) {
+ return true;
+ }
+ }
+ catch (Exception e) {
+ log.error("Failed to update database lock: " + e, e);
+ }
+ return false;
+ }
+}
Propchange: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DefaultDatabaseLocker.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java?rev=424328&r1=424327&r2=424328&view=diff
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java (original)
+++ incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/JDBCPersistenceAdapter.java Fri Jul 21 07:10:45 2006
@@ -16,15 +16,15 @@
*/
package org.apache.activemq.store.jdbc;
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.Set;
-
-import javax.sql.DataSource;
+import edu.emory.mathcs.backport.java.util.concurrent.ScheduledFuture;
+import edu.emory.mathcs.backport.java.util.concurrent.ScheduledThreadPoolExecutor;
+import edu.emory.mathcs.backport.java.util.concurrent.ThreadFactory;
+import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
import org.apache.activeio.command.WireFormat;
import org.apache.activeio.util.FactoryFinder;
+import org.apache.activemq.broker.BrokerService;
+import org.apache.activemq.broker.BrokerServiceAware;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
@@ -40,10 +40,12 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import edu.emory.mathcs.backport.java.util.concurrent.ScheduledFuture;
-import edu.emory.mathcs.backport.java.util.concurrent.ScheduledThreadPoolExecutor;
-import edu.emory.mathcs.backport.java.util.concurrent.ThreadFactory;
-import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
+import javax.sql.DataSource;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Set;
/**
* A {@link PersistenceAdapter} implementation using JDBC for persistence
@@ -57,19 +59,23 @@
*
* @version $Revision: 1.9 $
*/
-public class JDBCPersistenceAdapter extends DataSourceSupport implements PersistenceAdapter {
+public class JDBCPersistenceAdapter extends DataSourceSupport implements PersistenceAdapter, BrokerServiceAware {
private static final Log log = LogFactory.getLog(JDBCPersistenceAdapter.class);
private static FactoryFinder factoryFinder = new FactoryFinder("META-INF/services/org/apache/activemq/store/jdbc/");
private WireFormat wireFormat = new OpenWireFormat();
+ private BrokerService brokerService;
private Statements statements;
private JDBCAdapter adapter;
private MemoryTransactionStore transactionStore;
private ScheduledThreadPoolExecutor clockDaemon;
private ScheduledFuture clockTicket;
- int cleanupPeriod = 1000 * 60 * 5;
+ private int cleanupPeriod = 1000 * 60 * 5;
private boolean useExternalMessageReferences;
+ private boolean useDatabaseLock = true;
+ private int lockKeepAlivePeriod = 0;
+ private DatabaseLocker databaseLocker;
public JDBCPersistenceAdapter() {
}
@@ -156,6 +162,16 @@
} finally {
transactionContext.commit();
}
+
+ if (isUseDatabaseLock()) {
+ DatabaseLocker service = getDatabaseLocker();
+ if (service == null) {
+ log.warn("No databaseLocker configured for the JDBC Persistence Adapter");
+ }
+ else {
+ service.start();
+ }
+ }
cleanup();
@@ -175,6 +191,10 @@
clockTicket = null;
clockDaemon.shutdown();
}
+ DatabaseLocker service = getDatabaseLocker();
+ if (service != null) {
+ service.stop();
+ }
}
public void cleanup() {
@@ -227,6 +247,36 @@
return adapter;
}
+
+ public DatabaseLocker getDatabaseLocker() throws IOException {
+ if (databaseLocker == null) {
+ databaseLocker = createDatabaseLocker();
+ if (lockKeepAlivePeriod > 0) {
+ getScheduledThreadPoolExecutor().scheduleAtFixedRate(new Runnable() {
+ public void run() {
+ databaseLockKeepAlive();
+ }
+ }, lockKeepAlivePeriod, lockKeepAlivePeriod, TimeUnit.MILLISECONDS);
+ }
+ }
+ return databaseLocker;
+ }
+
+ /**
+ * Sets the database locker strategy to use to lock the database on startup
+ */
+ public void setDatabaseLocker(DatabaseLocker databaseLocker) {
+ this.databaseLocker = databaseLocker;
+ }
+
+ public BrokerService getBrokerService() {
+ return brokerService;
+ }
+
+ public void setBrokerService(BrokerService brokerService) {
+ this.brokerService = brokerService;
+ }
+
/**
* @throws IOException
*/
@@ -342,6 +392,15 @@
this.useExternalMessageReferences = useExternalMessageReferences;
}
+
+ public boolean isUseDatabaseLock() {
+ return useDatabaseLock;
+ }
+
+ public void setUseDatabaseLock(boolean useDatabaseLock) {
+ this.useDatabaseLock = useDatabaseLock;
+ }
+
static public void log(String msg, SQLException e) {
String s = msg+e.getMessage();
while( e.getNextException() != null ) {
@@ -368,4 +427,37 @@
public void setUsageManager(UsageManager usageManager) {
}
+
+ protected void databaseLockKeepAlive() {
+ boolean stop = false;
+ try {
+ DatabaseLocker locker = getDatabaseLocker();
+ if (locker != null) {
+ if (!locker.keepAlive()) {
+ stop = true;
+ }
+ }
+ }
+ catch (IOException e) {
+ log.error("Failed to get database when trying keepalive: " + e, e);
+ }
+ if (stop) {
+ stopBroker();
+ }
+ }
+
+ protected void stopBroker() {
+ // we can no longer keep the lock so lets fail
+ log.info("No longer able to keep the exclusive lock so giving up being a master");
+ try {
+ brokerService.stop();
+ }
+ catch (Exception e) {
+ log.warn("Failed to stop broker");
+ }
+ }
+
+ protected DatabaseLocker createDatabaseLocker() throws IOException {
+ return new DefaultDatabaseLocker(getDataSource(), getStatements());
+ }
}
Modified: incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/Statements.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/Statements.java?rev=424328&r1=424327&r2=424328&view=diff
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/Statements.java (original)
+++ incubator/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/store/jdbc/Statements.java Fri Jul 21 07:10:45 2006
@@ -27,6 +27,7 @@
private String tablePrefix = "";
protected String messageTableName = "ACTIVEMQ_MSGS";
protected String durableSubAcksTableName = "ACTIVEMQ_ACKS";
+ protected String lockTableName = "ACTIVEMQ_LOCK";
protected String binaryDataType = "BLOB";
protected String containerNameDataType = "VARCHAR(250)";
@@ -57,6 +58,9 @@
private String deleteOldMessagesStatement;
private String[] createSchemaStatements;
private String[] dropSchemaStatements;
+ private String lockCreateStatement;
+ private String lockUpdateStatement;
+ private boolean useLockCreateWhereClause;
public String[] getCreateSchemaStatements() {
if (createSchemaStatements == null) {
@@ -75,7 +79,11 @@
"CREATE TABLE " + getFullAckTableName() + "(" + "CONTAINER " + containerNameDataType + " NOT NULL"
+ ", CLIENT_ID " + stringIdDataType + " NOT NULL" + ", SUB_NAME " + stringIdDataType
+ " NOT NULL" + ", SELECTOR " + stringIdDataType + ", LAST_ACKED_ID " + sequenceDataType
- + ", PRIMARY KEY ( CONTAINER, CLIENT_ID, SUB_NAME))", };
+ + ", PRIMARY KEY ( CONTAINER, CLIENT_ID, SUB_NAME))",
+ "CREATE TABLE " + getFullLockTableName() + "( ID " + longDataType + ", TIME " + longDataType
+ + ", BROKER_NAME " + stringIdDataType + ", PRIMARY KEY (ID) )",
+ "INSERT INTO " + getFullLockTableName() + "(ID) VALUES (1)",
+ };
}
return createSchemaStatements;
}
@@ -220,12 +228,30 @@
public String getDeleteOldMessagesStatement() {
if (deleteOldMessagesStatement == null) {
deleteOldMessagesStatement = "DELETE FROM " + getFullMessageTableName()
- + " WHERE ( EXPIRATION<>0 AND EXPIRATION<?) OR ID <= " + "( SELECT min(" + getFullAckTableName()
- + ".LAST_ACKED_ID) " + "FROM " + getFullAckTableName() + " WHERE " + getFullAckTableName()
- + ".CONTAINER=" + getFullMessageTableName() + ".CONTAINER)";
+ + " WHERE ( EXPIRATION<>0 AND EXPIRATION<?) OR ID <= " + "( SELECT min(" + getFullAckTableName()
+ + ".LAST_ACKED_ID) " + "FROM " + getFullAckTableName() + " WHERE " + getFullAckTableName()
+ + ".CONTAINER=" + getFullMessageTableName() + ".CONTAINER)";
}
return deleteOldMessagesStatement;
}
+
+ public String getLockCreateStatement() {
+ if (lockCreateStatement == null) {
+ lockCreateStatement = "SELECT * FROM " + getFullLockTableName();
+ if (useLockCreateWhereClause) {
+ lockCreateStatement += " WHERE ID = 1";
+ }
+ lockCreateStatement += " FOR UPDATE";
+ }
+ return lockCreateStatement;
+ }
+
+ public String getLockUpdateStatement() {
+ if (lockUpdateStatement == null) {
+ lockUpdateStatement = "UPDATE " + getFullLockTableName() + " SET time = ? WHERE ID = 1";
+ }
+ return lockUpdateStatement;
+ }
public String getFullMessageTableName() {
return getTablePrefix() + getMessageTableName();
@@ -234,7 +260,12 @@
public String getFullAckTableName() {
return getTablePrefix() + getDurableSubAcksTableName();
}
+
+ public String getFullLockTableName() {
+ return getTablePrefix() + getLockTableName();
+ }
+
/**
* @return Returns the containerNameDataType.
*/
@@ -339,6 +370,14 @@
public void setDurableSubAcksTableName(String durableSubAcksTableName) {
this.durableSubAcksTableName = durableSubAcksTableName;
}
+
+ public String getLockTableName() {
+ return lockTableName;
+ }
+
+ public void setLockTableName(String lockTableName) {
+ this.lockTableName = lockTableName;
+ }
public String getLongDataType() {
return longDataType;
@@ -444,4 +483,19 @@
this.updateMessageStatement = updateMessageStatment;
}
+ public boolean isUseLockCreateWhereClause() {
+ return useLockCreateWhereClause;
+ }
+
+ public void setUseLockCreateWhereClause(boolean useLockCreateWhereClause) {
+ this.useLockCreateWhereClause = useLockCreateWhereClause;
+ }
+
+ public void setLockCreateStatement(String lockCreateStatement) {
+ this.lockCreateStatement = lockCreateStatement;
+ }
+
+ public void setLockUpdateStatement(String lockUpdateStatement) {
+ this.lockUpdateStatement = lockUpdateStatement;
+ }
}