mirror of https://github.com/apache/openjpa.git
OPENJPA-963: commit patch provided by Donald Woods
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@756193 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1d92b9a5c0
commit
9e683c7612
|
@ -4184,7 +4184,7 @@ public class DBDictionary
|
||||||
* implementation of setting query and lock timeouts.
|
* implementation of setting query and lock timeouts.
|
||||||
*
|
*
|
||||||
* @param stmnt
|
* @param stmnt
|
||||||
* @param fetch
|
* @param fetch - optional lock and query timeouts in milliseconds
|
||||||
* @param forUpdate - true if we should also try setting a lock timeout
|
* @param forUpdate - true if we should also try setting a lock timeout
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
|
@ -4210,7 +4210,7 @@ public class DBDictionary
|
||||||
* implementation of setting query and lock timeouts.
|
* implementation of setting query and lock timeouts.
|
||||||
*
|
*
|
||||||
* @param stmnt
|
* @param stmnt
|
||||||
* @param fetch
|
* @param conf - optional lock and query timeouts in milliseconds
|
||||||
* @param forUpdate - true if we should also try setting a lock timeout
|
* @param forUpdate - true if we should also try setting a lock timeout
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
|
@ -4229,22 +4229,44 @@ public class DBDictionary
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is to provide override for non-JDBC or JDBC-like
|
* Provides the default validation handling of setting a query timeout.
|
||||||
* implementation of setting query timeout.
|
* @param stmnt
|
||||||
|
* @param timeout in milliseconds
|
||||||
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public void setQueryTimeout(PreparedStatement stmnt, int timeout)
|
public void setQueryTimeout(PreparedStatement stmnt, int timeout)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
if (supportsQueryTimeout && timeout >= 0) {
|
if (supportsQueryTimeout) {
|
||||||
if (timeout > 0 && timeout < 1000) {
|
if (timeout == -1) {
|
||||||
|
// special OpenJPA allowed case denoting no timeout
|
||||||
|
timeout = 0;
|
||||||
|
} else if (timeout < 0) {
|
||||||
|
if (log.isWarnEnabled())
|
||||||
|
log.warn(_loc.get("invalid-timeout", new Integer(timeout)));
|
||||||
|
return;
|
||||||
|
} else if (timeout > 0 && timeout < 1000) {
|
||||||
|
// round up to 1 sec
|
||||||
timeout = 1000;
|
timeout = 1000;
|
||||||
Log log = conf.getLog(JDBCConfiguration.LOG_JDBC);
|
|
||||||
if (log.isWarnEnabled())
|
if (log.isWarnEnabled())
|
||||||
log.warn(_loc.get("millis-query-timeout"));
|
log.warn(_loc.get("millis-query-timeout"));
|
||||||
}
|
}
|
||||||
stmnt.setQueryTimeout(timeout / 1000);
|
setStatementQueryTimeout(stmnt, timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow subclasses to provide DB unique override implementations of
|
||||||
|
* setting query timeouts, while preserving the default timeout logic
|
||||||
|
* in the public setQueryTimeout method.
|
||||||
|
* @param stmnt
|
||||||
|
* @param timeout in milliseconds
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
protected void setStatementQueryTimeout(PreparedStatement stmnt,
|
||||||
|
int timeout) throws SQLException {
|
||||||
|
// JDBC uses seconds, so we'll do a simple round-down conversion here
|
||||||
|
stmnt.setQueryTimeout(timeout / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// ConnectionDecorator implementation
|
// ConnectionDecorator implementation
|
||||||
|
|
|
@ -75,3 +75,5 @@ objectid-abstract: Cannot create new application identity instance for \
|
||||||
abstract class "{0}".
|
abstract class "{0}".
|
||||||
query-failed: A query statement timeout has occurred.
|
query-failed: A query statement timeout has occurred.
|
||||||
query-timeout: A query statement timeout (set to {0} milliseconds) has occurred.
|
query-timeout: A query statement timeout (set to {0} milliseconds) has occurred.
|
||||||
|
invalid-timeout: An invalid timeout of {0} milliseconds was ignored. \
|
||||||
|
Expected a value that is greater than or equal to zero.
|
||||||
|
|
|
@ -16,18 +16,24 @@ package org.apache.openjpa.persistence.query;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
|
||||||
|
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||||
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||||
import org.apache.openjpa.jdbc.sql.DBDictionary;
|
import org.apache.openjpa.jdbc.sql.DBDictionary;
|
||||||
import org.apache.openjpa.jdbc.sql.DerbyDictionary;
|
import org.apache.openjpa.jdbc.sql.DerbyDictionary;
|
||||||
import org.apache.openjpa.kernel.Broker;
|
import org.apache.openjpa.kernel.Broker;
|
||||||
import org.apache.openjpa.lib.log.Log;
|
import org.apache.openjpa.lib.log.Log;
|
||||||
import org.apache.openjpa.persistence.JPAFacadeHelper;
|
import org.apache.openjpa.persistence.JPAFacadeHelper;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAEntityManager;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAPersistence;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAQuery;
|
||||||
import org.apache.openjpa.persistence.PersistenceException;
|
import org.apache.openjpa.persistence.PersistenceException;
|
||||||
import org.apache.openjpa.persistence.QueryTimeoutException;
|
import org.apache.openjpa.persistence.QueryTimeoutException;
|
||||||
import org.apache.openjpa.persistence.query.common.apps.QTimeout;
|
import org.apache.openjpa.persistence.query.common.apps.QTimeout;
|
||||||
|
@ -36,14 +42,38 @@ import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the new query timeout hint support in the JPA 2.0 spec.
|
* Tests the new query timeout hint support in the JPA 2.0 spec.
|
||||||
|
* Query timeout scenarios being tested:
|
||||||
|
* 1) By default, there is no timeout
|
||||||
|
* 2) Setting timeout to 0 is same as no timeout (JDBC defined)
|
||||||
|
* 2.1) using Map properties on createEMF (or PU properties)
|
||||||
|
* 2.2) using the QueryHint annotation
|
||||||
|
* 2.3) using setHint()
|
||||||
|
* 3) Setting timeout to msecs < DELAY value causes new
|
||||||
|
* javax.persistence.QueryTimeoutException for databases that do not
|
||||||
|
* cause a rollback or a PersistenceException if they do, when set by:
|
||||||
|
* 3.1) using persistence.xml PU properties (or createEMF Map properties)
|
||||||
|
* 3.2) using the QueryHint annotation
|
||||||
|
* 3.3) calling setHint()
|
||||||
|
* Query operations to validate through cross coverage of items #1-#3:
|
||||||
|
* a) getResultList()
|
||||||
|
* b) getSingleResult()
|
||||||
|
* c) executeUpdate()
|
||||||
|
* Other behaviors to test for:
|
||||||
|
* 4) Setting timeout to < 0 should be treated as no timeout supplied
|
||||||
|
* 5) Updates after EM.find()/findAll() are not affected by query timeout
|
||||||
|
* Exception generation to test for:
|
||||||
|
* If the DB query timeout does not cause a transaction rollback, then a
|
||||||
|
* QueryTimeoutException should be thrown.
|
||||||
|
* Applicable to: unknown
|
||||||
|
* Else if the DB query timeout causes a transaction rollback, then a
|
||||||
|
* PersistenceException should be thrown instead of a QTE.
|
||||||
|
* Applicable to: Derby
|
||||||
*
|
*
|
||||||
* @version $Rev$ $Date$
|
* @version $Rev$ $Date$
|
||||||
*/
|
*/
|
||||||
public class TestQueryTimeout extends SQLListenerTestCase {
|
public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
|
|
||||||
private boolean skipTests = false;
|
private boolean skipTests = false;
|
||||||
// does the DB platform allow retry instead of forcing transaction rollback
|
|
||||||
private boolean supportsQueryTimeoutException = false;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
|
@ -57,20 +87,24 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
// exception type to catch
|
// exception type to catch
|
||||||
DBDictionary dict = ((JDBCConfiguration) emf.getConfiguration())
|
DBDictionary dict = ((JDBCConfiguration) emf.getConfiguration())
|
||||||
.getDBDictionaryInstance();
|
.getDBDictionaryInstance();
|
||||||
if ((dict.supportsQueryTimeout) && (dict instanceof DerbyDictionary)) {
|
if (dict.supportsQueryTimeout) {
|
||||||
// set whether we expect to see QueryTimeoutException or
|
if (!(dict instanceof DerbyDictionary)) {
|
||||||
// PersistenceException
|
// FIXME drwoods - OPENJPA-964 - haven't determined what the
|
||||||
supportsQueryTimeoutException = false;
|
// other DBs support
|
||||||
} else {
|
// setQueryTimeout is not working with DB2 v9.5.3a on Windows
|
||||||
// FIXME drwoods - OPENJPA-964 - haven't determined what the other
|
getLog().info("FIXME - TestQueryTimeout tests are being " +
|
||||||
// DBs support
|
"skipped, as tests are not being run against a Derby DB.");
|
||||||
// setQueryTimeout is not working with DB2 v9.5.3a on Windows...
|
|
||||||
getLog().info("TestQueryTimeout tests are being skipped, due to " +
|
|
||||||
"DB not supporting Query Timeouts.");
|
|
||||||
skipTests = true;
|
skipTests = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
getLog().info("TestQueryTimeout tests are being skipped, " +
|
||||||
|
"due to DB not supporting Query Timeouts.");
|
||||||
|
skipTests = true;
|
||||||
|
}
|
||||||
|
if (skipTests)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// create some initial entities
|
||||||
try {
|
try {
|
||||||
em = emf.createEntityManager();
|
em = emf.createEntityManager();
|
||||||
assertNotNull(em);
|
assertNotNull(em);
|
||||||
|
@ -89,53 +123,50 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute some native SQL with no timeouts
|
// create delay function only on Derby, other DBs require manual setup
|
||||||
if (dict instanceof DerbyDictionary) {
|
if (dict instanceof DerbyDictionary) {
|
||||||
getLog().trace("setUp() - creating DELAY function only for Derby." +
|
getLog().trace("setUp() - creating DELAY function only for " +
|
||||||
" Other DBs require manual setup.");
|
"Derby. Other DBs require manual setup.");
|
||||||
// remove existing function if it exists and ignore any errors
|
// remove existing function if it exists and recreate
|
||||||
|
try {
|
||||||
exec(true, 0, "DROP FUNCTION DELAY");
|
exec(true, 0, "DROP FUNCTION DELAY");
|
||||||
exec(false, 0, "CREATE FUNCTION DELAY(SECONDS INTEGER, " +
|
exec(false, 0, "CREATE FUNCTION DELAY(SECONDS INTEGER, " +
|
||||||
"VALUE INTEGER) RETURNS INTEGER PARAMETER STYLE JAVA NO SQL " +
|
"VALUE INTEGER) RETURNS INTEGER PARAMETER STYLE JAVA " +
|
||||||
"LANGUAGE JAVA EXTERNAL NAME 'org.apache.openjpa.persistence." +
|
"NO SQL LANGUAGE JAVA EXTERNAL NAME " +
|
||||||
|
"'org.apache.openjpa.persistence." +
|
||||||
"query.TestQueryTimeout.delay'");
|
"query.TestQueryTimeout.delay'");
|
||||||
|
} catch (SQLException sqe) {
|
||||||
|
fail(sqe.toString());
|
||||||
}
|
}
|
||||||
getLog().trace("setUp() - creating BEFORE UPDATE/INSERT TRIGGERs for " +
|
}
|
||||||
"all DBs");
|
|
||||||
|
// create triggers on all DBs
|
||||||
|
try {
|
||||||
|
getLog().trace("setUp() - creating BEFORE UPDATE/INSERT " +
|
||||||
|
"TRIGGERs for all DBs");
|
||||||
exec(false, 0, "CREATE TRIGGER t1 NO CASCADE BEFORE UPDATE ON " +
|
exec(false, 0, "CREATE TRIGGER t1 NO CASCADE BEFORE UPDATE ON " +
|
||||||
"qtimeout FOR EACH ROW MODE DB2SQL values DELAY(2,-1)");
|
"qtimeout FOR EACH ROW MODE DB2SQL values DELAY(2,-1)");
|
||||||
exec(false, 0, "CREATE TRIGGER t2 NO CASCADE BEFORE INSERT ON " +
|
exec(false, 0, "CREATE TRIGGER t2 NO CASCADE BEFORE INSERT ON " +
|
||||||
"qtimeout FOR EACH ROW MODE DB2SQL values DELAY(2,-2)");
|
"qtimeout FOR EACH ROW MODE DB2SQL values DELAY(2,-2)");
|
||||||
// Don't include a DELETE trigger, as it slows down the DROP_TABLES
|
// Don't include a DELETE trigger, as it slows down the DROP_TABLES
|
||||||
// cleanup between tests
|
// cleanup between tests
|
||||||
// exec(0, "CREATE TRIGGER t3 NO CASCADE BEFORE DELETE ON qtimeout " +
|
// exec(0, "CREATE TRIGGER t3 NO CASCADE BEFORE DELETE ON " +
|
||||||
// "FOR EACH ROW MODE DB2SQL values DELAY(2,-3)");
|
// "qtimeout FOR EACH ROW MODE DB2SQL values DELAY(2,-3)");
|
||||||
|
} catch (SQLException sqe) {
|
||||||
|
if (dict instanceof DerbyDictionary) {
|
||||||
|
// Always fail if we couldn't create triggers in Derby
|
||||||
|
fail(sqe.toString());
|
||||||
|
} else {
|
||||||
|
// just disable tests for other DBs
|
||||||
|
getLog().info("TestQueryTimeout tests are being skipped, " +
|
||||||
|
"due to DB delay() function missing and/or problems " +
|
||||||
|
"creating the required triggers. DBs other than " +
|
||||||
|
"Derby require manual setup steps for these tests.");
|
||||||
|
skipTests = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Query timeout scenarios to test for:
|
|
||||||
* 1) By default, there is no timeout
|
|
||||||
* 2) Setting timeout to 0 is same as no timeout (JDBC defined)
|
|
||||||
* 2.1) using the QueryHint annotation
|
|
||||||
* 2.2) calling setHint()
|
|
||||||
* 3) Setting timeout to msecs < DELAY value causes new
|
|
||||||
* javax.persistence.QueryTimeoutException when set by:
|
|
||||||
* 3.1) using the QueryHint annotation
|
|
||||||
* 3.2) calling setHint()
|
|
||||||
* Operations to validate through cross coverage of items #1-#3:
|
|
||||||
* a) getResultList()
|
|
||||||
* b) getSingleResult()
|
|
||||||
* c) executeUpdate()
|
|
||||||
* Other behaviors to test for:
|
|
||||||
* 4) Setting timeout to < 0 should be treated as no timeout supplied
|
|
||||||
* Exception generation to test for:
|
|
||||||
* If the DB query timeout does not cause a transaction rollback, then a
|
|
||||||
* QueryTimeoutException should be thrown.
|
|
||||||
* Applicable to: unknown
|
|
||||||
* Else if the DB query timeout causes a transaction rollback, then a
|
|
||||||
* PersistenceException should be thrown instead of a QTE.
|
|
||||||
* Applicable to: Derby
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scenario being tested: 1a) By default, there is no timeout for queries.
|
* Scenario being tested: 1a) By default, there is no timeout for queries.
|
||||||
|
@ -186,29 +217,29 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
if (skipTests) {
|
if (skipTests) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getLog().trace("testQueryTimeout1c() - No Update timeout");
|
getLog().trace("testQueryTimeout1c() - No executeUpdate timeout");
|
||||||
EntityManager em = null;
|
EntityManager em = null;
|
||||||
try {
|
try {
|
||||||
em = emf.createEntityManager();
|
em = emf.createEntityManager();
|
||||||
assertNotNull(em);
|
assertNotNull(em);
|
||||||
|
Query q = em.createQuery("UPDATE QTimeout q SET q.stringField = :strVal WHERE q.id = 1");
|
||||||
|
q.setParameter("strVal", new String("updated"));
|
||||||
|
// verify no default javax.persistence.query.timeout is supplied
|
||||||
|
Map<String, Object> hints = q.getHints();
|
||||||
|
assertFalse(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
try {
|
try {
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
QTimeout qt = em.find(QTimeout.class, new Integer(1));
|
|
||||||
em.getTransaction().begin();
|
em.getTransaction().begin();
|
||||||
qt.setStringField("updated");
|
int count = q.executeUpdate();
|
||||||
em.flush();
|
|
||||||
em.getTransaction().commit();
|
em.getTransaction().commit();
|
||||||
long endTime = System.currentTimeMillis();
|
long endTime = System.currentTimeMillis();
|
||||||
long runTime = endTime - startTime;
|
long runTime = endTime - startTime;
|
||||||
getLog().trace("testQueryTimeout1c() - EM find/update runTime" +
|
getLog().trace("testQueryTimeout1c() - executeUpdate runTime " +
|
||||||
"msecs=" + runTime);
|
"msecs=" + runTime);
|
||||||
|
assertTrue("Verify we received one result.", (count == 1));
|
||||||
// Hack - Windows sometimes returns 1999 instead of 2000+
|
// Hack - Windows sometimes returns 1999 instead of 2000+
|
||||||
assertTrue("Should have taken 2+ secs, but was msecs=" +
|
assertTrue("Should have taken 2+ secs, but was msecs=" +
|
||||||
runTime, runTime > 1900);
|
runTime, runTime > 1900);
|
||||||
em.clear();
|
|
||||||
qt = em.find(QTimeout.class, new Integer(1));
|
|
||||||
assertEquals("Verify the entity was updated.",
|
|
||||||
qt.getStringField(), "updated");
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("Unexpected testQueryTimeout1c() exception = " + e);
|
fail("Unexpected testQueryTimeout1c() exception = " + e);
|
||||||
}
|
}
|
||||||
|
@ -220,16 +251,76 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scenario being tested: 2.1.a) Explicit annotated QueryHint of timeout=0
|
* Scenario being tested: 2.1.b) Explicit Map of properties to createEMF
|
||||||
|
* with timeout=0 is treated the same as the default no query timeout.
|
||||||
|
* Expected Results: The DELAY function is being called and the query
|
||||||
|
* takes 2000+ msecs to complete.
|
||||||
|
*/
|
||||||
|
public void testQueryTimeout21b() {
|
||||||
|
if (skipTests) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getLog().trace("testQueryTimeout21b() - Map(timeout=0)");
|
||||||
|
OpenJPAEntityManagerFactory emf = null;
|
||||||
|
OpenJPAEntityManager em = null;
|
||||||
|
Integer setTime = new Integer(0);
|
||||||
|
// create the Map to test overrides
|
||||||
|
Map<String,String >props = new HashMap<String,String>();
|
||||||
|
props.put("javax.persistence.query.timeout", "0");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// create our EMF with our timeout property
|
||||||
|
emf = OpenJPAPersistence.createEntityManagerFactory(
|
||||||
|
"qtimeout-no-properties", "persistence3.xml", props);
|
||||||
|
assertNotNull(emf);
|
||||||
|
// verify Map properties updated the config
|
||||||
|
OpenJPAConfiguration conf = emf.getConfiguration();
|
||||||
|
assertNotNull(conf);
|
||||||
|
assertEquals("Map provided query timeout", setTime.intValue(),
|
||||||
|
conf.getQueryTimeout());
|
||||||
|
// verify no default javax.persistence.query.timeout is supplied
|
||||||
|
// as the Map properties are not passed through as hints
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
assertNotNull(em);
|
||||||
|
OpenJPAQuery q = em.createNamedQuery("NoHintSingle");
|
||||||
|
Map<String, Object> hints = q.getHints();
|
||||||
|
assertFalse(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
|
// verify internal config values were updated
|
||||||
|
assertEquals("Map provided query timeout", setTime.intValue(),
|
||||||
|
q.getFetchPlan().getQueryTimeout());
|
||||||
|
|
||||||
|
try {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
Object result = q.getSingleResult();
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
long runTime = endTime - startTime;
|
||||||
|
getLog().trace("testQueryTimeout21b() - NoHintSingle runTime " +
|
||||||
|
"msecs=" + runTime);
|
||||||
|
// Hack - Windows sometimes returns 1999 instead of 2000+
|
||||||
|
assertTrue("Should have taken 2+ secs, but was msecs=" +
|
||||||
|
runTime, runTime > 1900);
|
||||||
|
assertNotNull("Verify we received a result.", result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail("Unexpected testQueryTimeout21b() exception = " + e);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if ((em != null) && em.isOpen()) {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scenario being tested: 2.2.a) Explicit annotated QueryHint of timeout=0
|
||||||
* is treated the same as the default no timeout for queries.
|
* is treated the same as the default no timeout for queries.
|
||||||
* Expected Results: The DELAY function is being called and the query
|
* Expected Results: The DELAY function is being called and the query
|
||||||
* takes 6000+ msecs to complete.
|
* takes 6000+ msecs to complete.
|
||||||
*/
|
*/
|
||||||
public void testQueryTimeout2a() {
|
public void testQueryTimeout22a() {
|
||||||
if (skipTests) {
|
if (skipTests) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getLog().trace("testQueryTimeout2a() - QueryHint=0");
|
getLog().trace("testQueryTimeout22a() - QueryHint=0");
|
||||||
EntityManager em = null;
|
EntityManager em = null;
|
||||||
try {
|
try {
|
||||||
em = emf.createEntityManager();
|
em = emf.createEntityManager();
|
||||||
|
@ -240,7 +331,7 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
assertTrue(hints.containsKey("javax.persistence.query.timeout"));
|
assertTrue(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
Integer timeout = new Integer(
|
Integer timeout = new Integer(
|
||||||
(String) hints.get("javax.persistence.query.timeout"));
|
(String) hints.get("javax.persistence.query.timeout"));
|
||||||
getLog().trace("testQueryTimeout2a() - Retrieved hint " +
|
getLog().trace("testQueryTimeout22a() - Retrieved hint " +
|
||||||
"javax.persistence.query.timeout=" + timeout);
|
"javax.persistence.query.timeout=" + timeout);
|
||||||
assertEquals(timeout, new Integer(0));
|
assertEquals(timeout, new Integer(0));
|
||||||
|
|
||||||
|
@ -250,14 +341,14 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
List results = q.getResultList();
|
List results = q.getResultList();
|
||||||
long endTime = System.currentTimeMillis();
|
long endTime = System.currentTimeMillis();
|
||||||
long runTime = endTime - startTime;
|
long runTime = endTime - startTime;
|
||||||
getLog().trace("testQueryTimeout2a() - Hint0msec runTime msecs="
|
getLog().trace("testQueryTimeout22a() - Hint0msec runTime msecs="
|
||||||
+ runTime);
|
+ runTime);
|
||||||
// Hack - Windows sometimes returns 5999 instead of 6000+
|
// Hack - Windows sometimes returns 5999 instead of 6000+
|
||||||
assertTrue("Should have taken 6+ secs, but was msecs=" +
|
assertTrue("Should have taken 6+ secs, but was msecs=" +
|
||||||
runTime, runTime > 5900);
|
runTime, runTime > 5900);
|
||||||
assertEquals("Verify we found 2 results.", 2, results.size());
|
assertEquals("Verify we found 2 results.", 2, results.size());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("Unexpected testQueryTimeout2a() exception = " + e);
|
fail("Unexpected testQueryTimeout22a() exception = " + e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if ((em != null) && em.isOpen()) {
|
if ((em != null) && em.isOpen()) {
|
||||||
|
@ -267,17 +358,17 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scenario being tested: 2.1.b) Explicit setHint of timeout=0 is treated
|
* Scenario being tested: 2.3.b) Explicit setHint of timeout=0 is treated
|
||||||
* the same as the default no timeout for queries.
|
* the same as the default no timeout for queries.
|
||||||
* Expected Results: The DELAY function is being called and the query
|
* Expected Results: The DELAY function is being called and the query
|
||||||
* takes 2000+ msecs to complete.
|
* takes 2000+ msecs to complete.
|
||||||
*/
|
*/
|
||||||
public void testQueryTimeout2b() {
|
public void testQueryTimeout23b() {
|
||||||
if (skipTests) {
|
if (skipTests) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Integer setTime = new Integer(0);
|
Integer setTime = new Integer(0);
|
||||||
getLog().trace("testQueryTimeout2b() - setHint(" + setTime + ")");
|
getLog().trace("testQueryTimeout23b() - setHint(" + setTime + ")");
|
||||||
EntityManager em = null;
|
EntityManager em = null;
|
||||||
try {
|
try {
|
||||||
em = emf.createEntityManager();
|
em = emf.createEntityManager();
|
||||||
|
@ -289,14 +380,14 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
assertFalse(hints.containsKey("javax.persistence.query.timeout"));
|
assertFalse(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
|
|
||||||
// update the timeout value to 0 and verify it was set
|
// update the timeout value to 0 and verify it was set
|
||||||
getLog().trace("testQueryTimeout2b() - Setting hint " +
|
getLog().trace("testQueryTimeout23b() - Setting hint " +
|
||||||
"javax.persistence.query.timeout=" + setTime);
|
"javax.persistence.query.timeout=" + setTime);
|
||||||
q.setHint("javax.persistence.query.timeout", setTime);
|
q.setHint("javax.persistence.query.timeout", setTime);
|
||||||
hints = q.getHints();
|
hints = q.getHints();
|
||||||
assertTrue(hints.containsKey("javax.persistence.query.timeout"));
|
assertTrue(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
Integer timeout = (Integer) hints.get(
|
Integer timeout = (Integer) hints.get(
|
||||||
"javax.persistence.query.timeout");
|
"javax.persistence.query.timeout");
|
||||||
getLog().trace("testQueryTimeout2b() - Retrieved hint " +
|
getLog().trace("testQueryTimeout23b() - Retrieved hint " +
|
||||||
"javax.persistence.query.timeout=" + timeout);
|
"javax.persistence.query.timeout=" + timeout);
|
||||||
assertEquals(timeout, setTime);
|
assertEquals(timeout, setTime);
|
||||||
|
|
||||||
|
@ -305,14 +396,14 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
Object result = q.getSingleResult();
|
Object result = q.getSingleResult();
|
||||||
long endTime = System.currentTimeMillis();
|
long endTime = System.currentTimeMillis();
|
||||||
long runTime = endTime - startTime;
|
long runTime = endTime - startTime;
|
||||||
getLog().trace("testQueryTimeout2b() - NoHintSingle runTime " +
|
getLog().trace("testQueryTimeout23b() - NoHintSingle runTime " +
|
||||||
"msecs=" + runTime);
|
"msecs=" + runTime);
|
||||||
// Hack - Windows sometimes returns 1999 instead of 2000+
|
// Hack - Windows sometimes returns 1999 instead of 2000+
|
||||||
assertTrue("Should have taken 2+ secs, but was msecs=" +
|
assertTrue("Should have taken 2+ secs, but was msecs=" +
|
||||||
runTime, runTime > 1900);
|
runTime, runTime > 1900);
|
||||||
assertNotNull("Verify we received a result.", result);
|
assertNotNull("Verify we received a result.", result);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("Unexpected testQueryTimeout2b() exception = " + e);
|
fail("Unexpected testQueryTimeout23b() exception = " + e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if ((em != null) && em.isOpen()) {
|
if ((em != null) && em.isOpen()) {
|
||||||
|
@ -322,32 +413,114 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scenario being tested: 3.1.a) Explicit annotated QueryHint of
|
* Scenario being tested: 3.1.c) Explicit persistence.xml provided PU
|
||||||
* timeout=1000 msecs will cause the query to timeout.
|
* property of timeout=1000 msecs will cause the query to timeout.
|
||||||
* Expected Results: QueryTimeoutException or PersistenceException
|
* Expected Results: The DELAY function is being called and the query
|
||||||
|
* takes 2000+ msecs to complete.
|
||||||
*/
|
*/
|
||||||
public void testQueryTimeout3a() {
|
public void testQueryTimeout31c() {
|
||||||
if (skipTests) {
|
if (skipTests) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
getLog().trace("testQueryTimeout31c() - PU(timeout=1000), executeUpdate timeout");
|
||||||
|
OpenJPAEntityManagerFactory emf = null;
|
||||||
|
OpenJPAEntityManager em = null;
|
||||||
Integer setTime = new Integer(1000);
|
Integer setTime = new Integer(1000);
|
||||||
getLog().trace("testQueryTimeout3a() - QueryHint(" + setTime + ")");
|
|
||||||
EntityManager em = null;
|
|
||||||
try {
|
try {
|
||||||
|
// create our EMF with our PU set timeout property
|
||||||
|
emf = OpenJPAPersistence.createEntityManagerFactory(
|
||||||
|
"qtimeout-1000msecs", "persistence3.xml");
|
||||||
|
assertNotNull(emf);
|
||||||
|
// verify PU properties updated the config
|
||||||
|
OpenJPAConfiguration conf = emf.getConfiguration();
|
||||||
|
assertNotNull(conf);
|
||||||
|
assertEquals("PU provided query timeout", setTime.intValue(),
|
||||||
|
conf.getQueryTimeout());
|
||||||
|
// create EM and Query
|
||||||
em = emf.createEntityManager();
|
em = emf.createEntityManager();
|
||||||
assertNotNull(em);
|
assertNotNull(em);
|
||||||
Query q = em.createNamedQuery("Hint1000msec");
|
OpenJPAQuery q = em.createNativeQuery("UPDATE QTimeout SET stringField = ? WHERE mod(DELAY(2,id),2)=0");
|
||||||
|
q.setParameter(1, new String("updated"));
|
||||||
|
// verify no default javax.persistence.query.timeout is supplied
|
||||||
|
Map<String, Object> hints = q.getHints();
|
||||||
|
assertFalse(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
|
// verify internal config values were updated
|
||||||
|
assertEquals("PU provided query timeout", setTime.intValue(),
|
||||||
|
q.getFetchPlan().getQueryTimeout());
|
||||||
|
|
||||||
|
// verify queryTimeout on EM find operations
|
||||||
|
try {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
int count = q.executeUpdate();
|
||||||
|
em.getTransaction().commit();
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
long runTime = endTime - startTime;
|
||||||
|
getLog().trace("testQueryTimeout31c() - executeUpdate runTime " +
|
||||||
|
"msecs=" + runTime);
|
||||||
|
fail("QueryTimeout for executeUpdate failed to cause an " +
|
||||||
|
"Exception in testQueryTimeout31c(" + setTime +
|
||||||
|
" mscs), runTime msecs=" + runTime);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// expected - Should cause a QueryTimeoutException for Derby
|
||||||
|
checkException("testQueryTimeout31c()", e);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if ((em != null) && em.isOpen()) {
|
||||||
|
if (em.getTransaction().isActive())
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scenario being tested: 3.2.a) Explicit annotated QueryHint of
|
||||||
|
* timeout=1000 msecs will override the PU and Map provided timeouts
|
||||||
|
* and cause the query to timeout.
|
||||||
|
* Expected Results: QueryTimeoutException or PersistenceException
|
||||||
|
*/
|
||||||
|
public void testQueryTimeout32a() {
|
||||||
|
if (skipTests) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getLog().trace("testQueryTimeout32a() - PU(1000), Map(0), QueryHint(1000)");
|
||||||
|
OpenJPAEntityManagerFactory emf = null;
|
||||||
|
OpenJPAEntityManager em = null;
|
||||||
|
Integer setTime = new Integer(0);
|
||||||
|
// create the Map to test overrides
|
||||||
|
Map<String,String> props = new HashMap<String,String>();
|
||||||
|
props.put("javax.persistence.query.timeout", "0");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// create our EMF with our PU set timeout property
|
||||||
|
emf = OpenJPAPersistence.createEntityManagerFactory(
|
||||||
|
"qtimeout-1000msecs", "persistence3.xml", props);
|
||||||
|
assertNotNull(emf);
|
||||||
|
// verify Map properties overrode the PU properties in config
|
||||||
|
OpenJPAConfiguration conf = emf.getConfiguration();
|
||||||
|
assertNotNull(conf);
|
||||||
|
assertEquals("Map provided query timeout", setTime.intValue(),
|
||||||
|
conf.getQueryTimeout());
|
||||||
|
// create EM and named query
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
assertNotNull(em);
|
||||||
|
OpenJPAQuery q = em.createNamedQuery("Hint1000msec");
|
||||||
|
setTime = 1000;
|
||||||
// verify javax.persistence.query.timeout hint via annotation set
|
// verify javax.persistence.query.timeout hint via annotation set
|
||||||
Map<String, Object> hints = q.getHints();
|
Map<String, Object> hints = q.getHints();
|
||||||
assertTrue(hints.containsKey("javax.persistence.query.timeout"));
|
assertTrue(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
Integer timeout = new Integer((String) hints.get(
|
Integer timeout = new Integer((String) hints.get(
|
||||||
"javax.persistence.query.timeout"));
|
"javax.persistence.query.timeout"));
|
||||||
getLog().trace(
|
getLog().trace(
|
||||||
"testQueryTimeout3a() - Found javax.persistence.query.timeout="
|
"testQueryTimeout32a() - Found javax.persistence.query.timeout="
|
||||||
+ timeout);
|
+ timeout);
|
||||||
assertTrue("Expected to find a javax.persistence.query.timeout="
|
assertTrue("Expected to find a javax.persistence.query.timeout="
|
||||||
+ setTime, (timeout.intValue() == setTime.intValue()));
|
+ setTime, (timeout.intValue() == setTime.intValue()));
|
||||||
|
// verify internal config values were updated
|
||||||
|
assertEquals("QueryHint provided query timeout", setTime.intValue(),
|
||||||
|
q.getFetchPlan().getQueryTimeout());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
@ -356,16 +529,16 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
long endTime = System.currentTimeMillis();
|
long endTime = System.currentTimeMillis();
|
||||||
long runTime = endTime - startTime;
|
long runTime = endTime - startTime;
|
||||||
getLog().trace(
|
getLog().trace(
|
||||||
"testQueryTimeout3a() - Hint1000msec runTime msecs="
|
"testQueryTimeout32a() - Hint1000msec runTime msecs="
|
||||||
+ runTime);
|
+ runTime);
|
||||||
//assertEquals("Should never get valid results due to the " +
|
//assertEquals("Should never get valid results due to the " +
|
||||||
// "timeout.", 2, results.size());
|
// "timeout.", 2, results.size());
|
||||||
fail("QueryTimeout annotation failed to cause an Exception " +
|
fail("QueryTimeout annotation failed to cause an Exception " +
|
||||||
"in testQueryTimeout3a(" + setTime +
|
"in testQueryTimeout32a(" + setTime +
|
||||||
" msecs), runTime msecs=" + runTime);
|
" msecs), runTime msecs=" + runTime);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// expected
|
// expected
|
||||||
checkException("testQueryTimeout3a()", e);
|
checkException("testQueryTimeout32a()", e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if ((em != null) && em.isOpen()) {
|
if ((em != null) && em.isOpen()) {
|
||||||
|
@ -375,16 +548,16 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scenario being tested: 3.2.b) Explicit setHint of timeout to 1000 msecs
|
* Scenario being tested: 3.3.b) Explicit setHint of timeout to 1000 msecs
|
||||||
* will cause the query to timeout.
|
* will cause the query to timeout.
|
||||||
* Expected Results: QueryTimeoutException or PersistenceException
|
* Expected Results: QueryTimeoutException or PersistenceException
|
||||||
*/
|
*/
|
||||||
public void testQueryTimeout3b() {
|
public void testQueryTimeout33b() {
|
||||||
if (skipTests) {
|
if (skipTests) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Integer setTime = new Integer(1000);
|
Integer setTime = new Integer(1000);
|
||||||
getLog().trace("testQueryTimeout3b() - setHint(" + setTime + ")");
|
getLog().trace("testQueryTimeout33b() - setHint(" + setTime + ")");
|
||||||
EntityManager em = null;
|
EntityManager em = null;
|
||||||
try {
|
try {
|
||||||
em = emf.createEntityManager();
|
em = emf.createEntityManager();
|
||||||
|
@ -396,7 +569,7 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
assertFalse(hints.containsKey("javax.persistence.query.timeout"));
|
assertFalse(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
|
|
||||||
// update the timeout value and verify it was set
|
// update the timeout value and verify it was set
|
||||||
getLog().trace("testQueryTimeout3b() - Setting hint " +
|
getLog().trace("testQueryTimeout33b() - Setting hint " +
|
||||||
"javax.persistence.query.timeout=" + setTime);
|
"javax.persistence.query.timeout=" + setTime);
|
||||||
q.setHint("javax.persistence.query.timeout", setTime);
|
q.setHint("javax.persistence.query.timeout", setTime);
|
||||||
hints = q.getHints();
|
hints = q.getHints();
|
||||||
|
@ -412,15 +585,15 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
long endTime = System.currentTimeMillis();
|
long endTime = System.currentTimeMillis();
|
||||||
long runTime = endTime - startTime;
|
long runTime = endTime - startTime;
|
||||||
getLog().trace(
|
getLog().trace(
|
||||||
"testQueryTimeout3b() - NoHintSingle runTime msecs="
|
"testQueryTimeout33b() - NoHintSingle runTime msecs="
|
||||||
+ runTime);
|
+ runTime);
|
||||||
//assertNull("Should never get valid result due to the timeout.", result);
|
//assertNull("Should never get valid result due to the timeout.", result);
|
||||||
fail("QueryTimeout annotation failed to cause an Exception " +
|
fail("QueryTimeout annotation failed to cause an Exception " +
|
||||||
"in testQueryTimeout3b(" + setTime +
|
"in testQueryTimeout33b(" + setTime +
|
||||||
" mscs), runTime msecs=" + runTime);
|
" mscs), runTime msecs=" + runTime);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// expected
|
// expected
|
||||||
checkException("testQueryTimeout3b()", e);
|
checkException("testQueryTimeout33b()", e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if ((em != null) && em.isOpen()) {
|
if ((em != null) && em.isOpen()) {
|
||||||
|
@ -429,6 +602,85 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scenario being tested: 3.3.c) Explicit setHint of timeout to 1000 msecs
|
||||||
|
* will cause the PU provided timeout=0 value to be overridden and the
|
||||||
|
* executeUpdate to timeout.
|
||||||
|
* Expected Results: QueryTimeoutException (Derby) or PersistenceException
|
||||||
|
*/
|
||||||
|
public void testQueryTimeout33c() {
|
||||||
|
if (skipTests) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getLog().trace("testQueryTimeout33c() - PU(timeout=0), setHint(1000), executeUpdate timeout");
|
||||||
|
OpenJPAEntityManagerFactory emf = null;
|
||||||
|
OpenJPAEntityManager em = null;
|
||||||
|
Integer setTime = new Integer(0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// create our EMF with our PU set timeout property
|
||||||
|
emf = OpenJPAPersistence.createEntityManagerFactory(
|
||||||
|
"qtimeout-0msecs", "persistence3.xml");
|
||||||
|
assertNotNull(emf);
|
||||||
|
// verify PU properties updated the config
|
||||||
|
OpenJPAConfiguration conf = emf.getConfiguration();
|
||||||
|
assertNotNull(conf);
|
||||||
|
assertEquals("PU provided no query timeout", setTime.intValue(),
|
||||||
|
conf.getQueryTimeout());
|
||||||
|
// create EM and Query
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
assertNotNull(em);
|
||||||
|
// Following fails to cause a SQLException, but takes 2+ secs
|
||||||
|
// Query q = em.createQuery("UPDATE QTimeout q SET q.stringField = :strVal WHERE q.id > 0");
|
||||||
|
// q.setParameter("strVal", new String("updated"));
|
||||||
|
// Following fails to cause a SQLException, but takes 2+ secs
|
||||||
|
// Query q = em.createNativeQuery("INSERT INTO QTimeout (id, stringField) VALUES (?,?)");
|
||||||
|
// q.setParameter(1, 99);
|
||||||
|
// q.setParameter(2, new String("inserted"));
|
||||||
|
OpenJPAQuery q = em.createNativeQuery("UPDATE QTimeout SET stringField = ? WHERE mod(DELAY(2,id),2)=0");
|
||||||
|
q.setParameter(1, new String("updated"));
|
||||||
|
// verify no default javax.persistence.query.timeout is supplied
|
||||||
|
Map<String, Object> hints = q.getHints();
|
||||||
|
assertFalse(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
|
// update the query timeout value and verify it was set
|
||||||
|
setTime = 1000;
|
||||||
|
getLog().trace("testQueryTimeout33c() - Setting hint " +
|
||||||
|
"javax.persistence.query.timeout=" + setTime);
|
||||||
|
q.setHint("javax.persistence.query.timeout", setTime);
|
||||||
|
hints = q.getHints();
|
||||||
|
assertTrue(hints.containsKey("javax.persistence.query.timeout"));
|
||||||
|
Integer timeout = (Integer) hints.get(
|
||||||
|
"javax.persistence.query.timeout");
|
||||||
|
assertEquals(timeout, setTime);
|
||||||
|
// verify internal config values were updated
|
||||||
|
assertEquals("PU provided query timeout", setTime.intValue(),
|
||||||
|
q.getFetchPlan().getQueryTimeout());
|
||||||
|
|
||||||
|
try {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
int count = q.executeUpdate();
|
||||||
|
em.getTransaction().commit();
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
long runTime = endTime - startTime;
|
||||||
|
getLog().trace("testQueryTimeout33c() - executeUpdate runTime " +
|
||||||
|
"msecs=" + runTime);
|
||||||
|
fail("QueryTimeout for executeUpdate failed to cause an " +
|
||||||
|
"Exception in testQueryTimeout33c(" + setTime +
|
||||||
|
" mscs), runTime msecs=" + runTime);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// expected - Should cause a QueryTimeoutException for Derby
|
||||||
|
checkException("testQueryTimeout33c()", e);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if ((em != null) && em.isOpen()) {
|
||||||
|
if (em.getTransaction().isActive())
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scenario being tested: 4) Timeouts < 0 are ignored and treated as the
|
* Scenario being tested: 4) Timeouts < 0 are ignored and treated as the
|
||||||
* default no timeout scenario.
|
* default no timeout scenario.
|
||||||
|
@ -487,6 +739,65 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scenario being tested: 5) PU Query timeout hints do not affect EM
|
||||||
|
* operations like updating Entities returned by EM.find()/findAll()
|
||||||
|
* Expected Results: The DELAY function is being called and the update
|
||||||
|
* takes 2000+ msecs to complete.
|
||||||
|
*/
|
||||||
|
public void testQueryTimeout5() {
|
||||||
|
if (skipTests) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getLog().trace("testQueryTimeout5() - No EM.find() update timeout");
|
||||||
|
OpenJPAEntityManagerFactory emf = null;
|
||||||
|
OpenJPAEntityManager em = null;
|
||||||
|
Integer setTime = new Integer(1000);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// create our EMF with our PU set timeout property
|
||||||
|
emf = OpenJPAPersistence.createEntityManagerFactory(
|
||||||
|
"qtimeout-1000msecs", "persistence3.xml");
|
||||||
|
assertNotNull(emf);
|
||||||
|
// verify PU properties updated the config
|
||||||
|
OpenJPAConfiguration conf = emf.getConfiguration();
|
||||||
|
assertNotNull(conf);
|
||||||
|
assertEquals("PU provided timeout", setTime.intValue(),
|
||||||
|
conf.getQueryTimeout());
|
||||||
|
// create EM
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
assertNotNull(em);
|
||||||
|
|
||||||
|
try {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
QTimeout qt = em.find(QTimeout.class, new Integer(1));
|
||||||
|
em.getTransaction().begin();
|
||||||
|
qt.setStringField("updated");
|
||||||
|
em.flush();
|
||||||
|
em.getTransaction().commit();
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
long runTime = endTime - startTime;
|
||||||
|
getLog().trace("testQueryTimeout1d() - EM find/update runTime" +
|
||||||
|
" msecs=" + runTime);
|
||||||
|
// Hack - Windows sometimes returns 1999 instead of 2000+
|
||||||
|
assertTrue("Should have taken 2+ secs, but was msecs=" +
|
||||||
|
runTime, runTime > 1900);
|
||||||
|
em.clear();
|
||||||
|
qt = em.find(QTimeout.class, new Integer(1));
|
||||||
|
assertEquals("Verify the entity was updated.",
|
||||||
|
qt.getStringField(), "updated");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// setting a timeout property via PU or Map shouldn't cause a
|
||||||
|
// timeout exception
|
||||||
|
fail("Unexpected testQueryTimeout5() exception = " + e);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if ((em != null) && em.isOpen()) {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal convenience method to execute SQL statements
|
* Internal convenience method to execute SQL statements
|
||||||
*
|
*
|
||||||
|
@ -495,7 +806,8 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
* @param timeoutSecs
|
* @param timeoutSecs
|
||||||
* @param fail
|
* @param fail
|
||||||
*/
|
*/
|
||||||
private void exec(boolean ignoreExceptions, int timeoutSecs, String sql) {
|
private void exec(boolean ignoreExceptions, int timeoutSecs, String sql)
|
||||||
|
throws SQLException {
|
||||||
EntityManager em = null;
|
EntityManager em = null;
|
||||||
Statement s = null;
|
Statement s = null;
|
||||||
try {
|
try {
|
||||||
|
@ -511,7 +823,8 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
s.execute(sql);
|
s.execute(sql);
|
||||||
} catch (SQLException sqe) {
|
} catch (SQLException sqe) {
|
||||||
if (!ignoreExceptions) {
|
if (!ignoreExceptions) {
|
||||||
fail(sqe.toString());
|
// fail(sqe.toString());
|
||||||
|
throw sqe;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
|
@ -544,13 +857,10 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
* @param e
|
* @param e
|
||||||
*/
|
*/
|
||||||
private void checkException(String test, Exception e) {
|
private void checkException(String test, Exception e) {
|
||||||
if (supportsQueryTimeoutException) {
|
// no easy way to determine exact Exception type for all DBs
|
||||||
assertTrue("Expected QueryTimeoutException instead of " + e,
|
assertTrue(test + " - UNEXPECTED Exception = " + e,
|
||||||
matchesExpectedException(QueryTimeoutException.class, e));
|
matchesExpectedException(QueryTimeoutException.class, e) ||
|
||||||
} else {
|
|
||||||
assertTrue("Expected PersistenceException instead of " + e,
|
|
||||||
matchesExpectedException(PersistenceException.class, e));
|
matchesExpectedException(PersistenceException.class, e));
|
||||||
}
|
|
||||||
getLog().trace(test + " - Caught expected Exception = " + e);
|
getLog().trace(test + " - Caught expected Exception = " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,6 +879,11 @@ public class TestQueryTimeout extends SQLListenerTestCase {
|
||||||
if (tested != null) {
|
if (tested != null) {
|
||||||
Class<?> testExClass = tested.getClass();
|
Class<?> testExClass = tested.getClass();
|
||||||
exMatched = expected.isAssignableFrom(testExClass);
|
exMatched = expected.isAssignableFrom(testExClass);
|
||||||
|
if (exMatched) {
|
||||||
|
// make sure it is our expected exception text from
|
||||||
|
// localizer.properties
|
||||||
|
exMatched = (tested.getMessage().indexOf("query statement timeout") != -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return exMatched;
|
return exMatched;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
version="1.0">
|
version="1.0">
|
||||||
|
|
||||||
<!-- Following 2 PUs are used by TestQueryProperties -->
|
<!-- Following PUs are used by TestQueryProperties and TestQueryTimeout -->
|
||||||
<persistence-unit name="qtimeout-no-properties">
|
<persistence-unit name="qtimeout-no-properties">
|
||||||
<class>org.apache.openjpa.persistence.query.common.apps.QTimeout</class>
|
<class>org.apache.openjpa.persistence.query.common.apps.QTimeout</class>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
@ -34,7 +34,13 @@
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
|
||||||
<!-- Following PU is used by TestQueryTimeout -->
|
<persistence-unit name="qtimeout-0msecs">
|
||||||
|
<class>org.apache.openjpa.persistence.query.common.apps.QTimeout</class>
|
||||||
|
<properties>
|
||||||
|
<property name="javax.persistence.query.timeout" value="0"/>
|
||||||
|
</properties>
|
||||||
|
</persistence-unit>
|
||||||
|
|
||||||
<persistence-unit name="qtimeout-1000msecs">
|
<persistence-unit name="qtimeout-1000msecs">
|
||||||
<class>org.apache.openjpa.persistence.query.common.apps.QTimeout</class>
|
<class>org.apache.openjpa.persistence.query.common.apps.QTimeout</class>
|
||||||
<properties>
|
<properties>
|
||||||
|
|
Loading…
Reference in New Issue