Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I risk a JDBC connection leak when streaming JOOQ results outside a try-with-resources block?

I have a JOOQ query where I want to avoid materializing all Records at the same time. (However, I am fine with jointly materializing all bean objects created from them.)

I have the following simple method to load the data:

public List<CustomerInfo> getCustomers() {
    return dslContext
                .selectFrom(CUSTOMER)
                // <-- note the missing .fetch()
                .stream()
                .map(CustomerInfo::new)
                .collect(Collectors.toList());
}

Can this lead to a JDBC connection leak in any circumstances? (e.g. an Exception in CustomerInfo::new)

like image 578
blubb Avatar asked Feb 22 '16 16:02

blubb


People also ask

What is JDBC connection leak?

A connection leak means some of the database request/transaction are not getting closed properly or are not getting committed and finally those connections are getting abondoned and closed permanently.

How to avoid connection Leak in java?

Use removeAbandoned, removeAbandonedTimeout and logAbandoned (if supported). This allows the pool to time the usage of a connection, and forcibly reclaim it.


1 Answers

I've tried my luck finding a way to register a reliable stream "completion" hook that fires on complete stream consumption or on any exception, but that's not possible, unfortunately: Register a Stream "completion" hook

So, indeed, the code you have shown is not correct. The correct way to operate with "lazy" streams (or Cursor) is to use the try-with-resources statement. The following two are equivalent:

// Using a Stream
try (Stream<CustomerRecord> stream = dslContext.selectFrom(CUSTOMER).stream()) {
    return stream.map(CustomerInfo::new).collect(Collectors.toList());
}

// Using a Cursor
try (Cursor<CustomerRecord> cursor = dslContext.selectFrom(CUSTOMER).fetchLazy()) {
    return cursor.stream().map(CustomerInfo::new).collect(Collectors.toList());
}

Notice also the ResultQuery.stream() javadoc:

This is essentially the same as fetchLazy() but instead of returning a Cursor, a Java 8 Stream is returned. Clients should ensure the Stream is properly closed, e.g. in a try-with-resources statement

like image 131
Lukas Eder Avatar answered Oct 16 '22 12:10

Lukas Eder