From c640a2a1db5797464bce44ccfe4674d8347c2a92 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Sat, 18 Aug 2012 21:18:18 +0200 Subject: [PATCH] [#1657] Reorganise the manual (126 / 177) --- .../src/main/resources/manual-2.5.xml | 219 +++++++++++++++++- 1 file changed, 215 insertions(+), 4 deletions(-) diff --git a/jOOQ-website/src/main/resources/manual-2.5.xml b/jOOQ-website/src/main/resources/manual-2.5.xml index 690f35a212..fdd642f42e 100644 --- a/jOOQ-website/src/main/resources/manual-2.5.xml +++ b/jOOQ-website/src/main/resources/manual-2.5.xml @@ -4924,17 +4924,181 @@ List> results = create.fetchMany("sp_help 'author'");]]>
Later fetching - + +

Asynchronously execute your SQL statements

+

+ Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here: +

+ + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); + +// This example actively waits for the result to be done +while (!future.isDone()) { + progressBar.increment(1); + Thread.sleep(50); +} + +// The result should be ready, now +Result result = future.get();]]> + +

+ Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own : +

+ + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> + +
ResultSet fetching - + +

Fetch data into JDBC ResultSets, rather than jOOQ Results

+

+ When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways: +

+ + + +

Transform jOOQ's Result into a JDBC ResultSet

+

+ Instead of operating on a JDBC ResultSet holding an open resource from your database, you can also let jOOQ's wrap itself in a . The advantage of this is that the so-created ResultSet has no open connection to the database. It is a completely in-memory ResultSet: +

+ + result = create.selectFrom(BOOK).fetch(); +ResultSet rs = result.intoResultSet();]]> + +

The inverse: Fetch data from a legacy ResultSet using jOOQ

+

+ The inverse of the above is possible too. Maybe, a legacy part of your application produces JDBC , and you want to turn them into a : +

+ + result = create.fetch(rs); + +// As a Cursor +Cursor cursor = create.fetchLazy(rs);]]> + +
Data type conversion - + +

Converting JDBC-compatible data types in your own custom data types

+

+ Apart from a few extra features (see the manual's section about and ), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the >U> type corresponds to your own user type. The Converter API is given here: +

+ + extends Serializable { + + /** + * Convert a database object to a user object + */ + U from(T databaseObject); + + /** + * Convert a user object to a database object + */ + T to(U userObject); + + /** + * The database type + */ + Class fromType(); + + /** + * The user type + */ + Class toType(); +}]]> + +

+ Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about . +

+ +

A Converter for GregorianCalendar

+

+ Here is a some more elaborate example involving a Converter for : +

+ + { + + @Override + public GregorianCalendar from(Timestamp databaseObject) { + GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance(); + calendar.setTimeInMillis(databaseObject.getTime()); + return calendar; + } + + @Override + public Timestamp to(GregorianCalendar userObject) { + return new Timestamp(userObject.getTime().getTime()); + } + + @Override + public Class fromType() { + return Timestamp.class; + } + + @Override + public Class toType() { + return GregorianCalendar.class; + } +} + +// Now you can fetch calendar values from jOOQ's API: +List dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); +List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); +]]> + +

Enum Converters

+

+ jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum: +

+ + { + public YNMConverter() { + super(String.class, YNM.class); + } +} + +// And you're all set for converting records to your custom Enum: +for (BookRecord book : create.selectFrom(BOOK).fetch()) { + switch (book.getValue(BOOK.I_LIKE, new YNMConverter())) { + case YES: System.out.println("I like this book : " + book.getTitle()); break; + case NO: System.out.println("I didn't like this book : " + book.getTitle()); break; + case MAYBE: System.out.println("I'm not sure about this book : " + book.getTitle()); break; + } +}]]> + +

Using Converters in generated source code

+

+ jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. +

+
@@ -4942,6 +5106,48 @@ List> results = create.fetchMany("sp_help 'author'");]]>
Static statements vs. Prepared Statements +

Static statements vs. Prepared Statements

+

+ With JDBC, you have full control over your SQL statements. You can decide yourself, if you want to execute a static without bind values, or a with (or without) bind values. But you have to decide early, which way to go. And you'll have to prevent SQL injection and syntax errors manually, when inlining your bind variables. +

+

+ With jOOQ, this is easier. As a matter of fact, it is plain simple. With jOOQ, you can just set a flag in your , and all queries produced by that factory will be executed as static statements, with all bind values inlined. An example is given here: +

+ + + + + + +

Reasons for choosing one or the other

+

+ Not all databases are equal. Some databases show improved performance if you use , as the database will then be able to re-use execution plans for identical SQL statements, regardless of actual bind values. This heavily improves the time it takes for soft-parsing a SQL statement. In other situations, assuming that bind values are irrelevant for SQL execution plans may be a bad idea, as you might run into "bind value peeking" issues. You may be better off spending the extra cost for a new hard-parse of your SQL statement and instead having the database fine-tune the new plan to the concrete bind values. +

+

+ Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values. +

+ +

Inlining bind values on a per-bind-value basis

+

+ Note that you don't have to inline all your bind values at once. If you know that a bind value is not really a variable and should be inlined explicitly, you can do so by using , as documented in the manual's section about +

@@ -6401,7 +6607,12 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
- Generated tables + Generated procedures + +
+ +
+ Generated UDTs