Skip to content

Commit

Permalink
#301 - MySQL specific issue - java.sql.SQLException: Streaming result…
Browse files Browse the repository at this point in the history
… set com.mysql.jdbc.RowDataDynamic@3ef4415f is still active. No statements may be issued when any streaming result sets a re open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries
  • Loading branch information
rbygrave committed May 29, 2015
1 parent 8fe91f6 commit 0013cb1
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ public enum OnQueryOnly {
COMMIT
}


/**
* Set to true for MySql, no other jdbc drivers need this workaround.
*/
protected boolean useExtraTransactionOnIterateSecondaryQueries;

/**
* The behaviour used when ending a read only transaction at read committed isolation level.
*/
Expand Down Expand Up @@ -153,6 +159,17 @@ public String getName() {
return name;
}

/**
* Return true if the JDBC driver does not allow additional queries to execute
* when a resultSet is being 'streamed' as is the case with findEach() etc.
* <p>
* Honestly, this is a workaround for a stupid MySql JDBC driver limitation.
* </p>
*/
public boolean useExtraTransactionOnIterateSecondaryQueries() {
return useExtraTransactionOnIterateSecondaryQueries;
}

/**
* Return a DB Sequence based IdGenerator.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class MySqlPlatform extends DatabasePlatform {
public MySqlPlatform() {
super();
this.name = "mysql";
this.useExtraTransactionOnIterateSecondaryQueries = true;
this.likeClause = "like ? escape''";
this.selectCountWithAlias = true;
this.dbEncrypt = new MySqlDbEncrypt();
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/avaje/ebeaninternal/api/LoadRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,11 @@ public Transaction getTransaction() {
return transaction;
}

/**
* Return true if the parent query is a findIterate() type query.
* So one of - findIterate(), findEach(), findEachWhile() or findVisit().
*/
public boolean isParentFindIterate() {
return parentRequest != null && parentRequest.getQuery().getType() == SpiQuery.Type.ITERATE;
}
}
5 changes: 5 additions & 0 deletions src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ enum Type {
*/
BEAN,

/**
* Find iterate type query - findEach(), findIterate() etc.
*/
ITERATE,

/**
* Find returning a List.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import javax.persistence.EntityNotFoundException;

import com.avaje.ebeaninternal.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -15,11 +16,6 @@
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebean.bean.ObjectGraphNode;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebeaninternal.api.LoadBeanBuffer;
import com.avaje.ebeaninternal.api.LoadBeanRequest;
import com.avaje.ebeaninternal.api.LoadManyRequest;
import com.avaje.ebeaninternal.api.LoadManyBuffer;
import com.avaje.ebeaninternal.api.SpiQuery;
import com.avaje.ebeaninternal.api.SpiQuery.Mode;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
Expand All @@ -36,8 +32,11 @@ public class DefaultBeanLoader {

private final DefaultServer server;

private final boolean onIterateUseExtraTxn;

protected DefaultBeanLoader(DefaultServer server) {
this.server = server;
this.onIterateUseExtraTxn = server.getDatabasePlatform().useExtraTransactionOnIterateSecondaryQueries();
}

/**
Expand Down Expand Up @@ -143,7 +142,17 @@ public void loadMany(LoadManyRequest loadRequest) {
query.select(many.getTargetIdProperty());
}

server.findList(query, loadRequest.getTransaction());
if (onIterateUseExtraTxn && loadRequest.isParentFindIterate()) {
// MySql - we need a different transaction to execute the secondary query
SpiTransaction extraTxn = server.createQueryTransaction();
try {
server.findList(query, extraTxn);
} finally {
extraTxn.end();
}
} else {
server.findList(query, loadRequest.getTransaction());
}

// check for BeanCollection's that where never processed
// in the +query or +lazy load due to no rows (predicates)
Expand Down Expand Up @@ -332,7 +341,18 @@ public void loadBean(LoadBeanRequest loadRequest) {
query.where().idIn(idList);
}

List<?> list = server.findList(query, loadRequest.getTransaction());
List<?> list;
if (onIterateUseExtraTxn && loadRequest.isParentFindIterate()) {
// MySql - we need a different transaction to execute the secondary query
SpiTransaction extraTxn = server.createQueryTransaction();
try {
list = server.findList(query, extraTxn);
} finally {
extraTxn.end();
}
} else {
list = server.findList(query, loadRequest.getTransaction());
}

if (loadRequest.isLoadCache()) {
for (int i = 0; i < list.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1318,7 +1318,7 @@ public <T> PagedList<T> findPagedList(Query<T> query, Transaction transaction, i

public <T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transaction t) {

SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);

request.initTransIfRequired();
request.findVisit(visitor);
Expand All @@ -1327,7 +1327,7 @@ public <T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transac

public <T> void findEach(Query<T> query, QueryEachConsumer<T> consumer, Transaction t) {

SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);

request.initTransIfRequired();
request.findEach(consumer);
Expand All @@ -1336,7 +1336,7 @@ public <T> void findEach(Query<T> query, QueryEachConsumer<T> consumer, Transact

public <T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer, Transaction t) {

SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);

request.initTransIfRequired();
request.findEachWhile(consumer);
Expand All @@ -1345,7 +1345,7 @@ public <T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer

public <T> QueryIterator<T> findIterate(Query<T> query, Transaction t) {

SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);

try {
request.initTransIfRequired();
Expand Down

0 comments on commit 0013cb1

Please sign in to comment.