A jOOQ-CodeGenerator to create vertx-ified DAOs and POJOs!
Perform all CRUD-operations asynchronously and convert your POJOs from/into a io.vertx.core.json.JsonObject
using the API and
driver of your choice.
- The main addition in this release is transaction support for reactive modules.
Transaction are now added onto the reactive variants of the
QueryExecutor
. There are two ways to work with transactions:- The manual mode involves starting and manually committing or rolling back the transaction.
Future<Void> transactionWork = dao.queryExecutor() .beginTransaction() .compose( transactionQE -> { //only work on the "transactional" QueryExecutor returned by the beginTransaction() method Future<Integer> insert1 = transactionQE.execute(dslContext -> dslContext.insertInto() ....; Future<Integer> insert2 = transactionQE.execute(dslContext -> dslContext.insertInto() ....; return CompositeFuture .all(insert1,insert2) .compose(v->transactionQE.commit() /*or .rollback()*/); //don't forget to commit your transaction });
- The "convenient mode" is the best choice for most situations. It allows you to work in a transactional context that
automatically commits your work when you are done. You can also return a value from your transactional work.
Future<Void> transactionWork = dao.queryExecutor() .transaction( transactionQE -> { //only work on the "transactional" QueryExecutor returned by the transaction() method Future<Integer> insert1 = transactionQE.execute(dslContext -> dslContext.insertInto() ....; Future<Integer> insert2 = transactionQE.execute(dslContext -> dslContext.insertInto() ....; return CompositeFuture.all(insert1,insert2); //or return some result });
- The manual mode involves starting and manually committing or rolling back the transaction.
- Another important change was the switch to a maintained fork of the async driver which was introduced in vertx 3.6.3 and will be the default implementation in the next releases. The API stays the same but the driver is written in Kotlin instead of Scala. Checkout the migration guide for more details.
- Lastly, some bugs have been fixed.
Fast, faster, reactive.
- Starting from this version on,
vertx-jooq
adds support for this winning, high performance postgres driver. - Finally added support for
DAO#insertReturning
for the async postgres driver. - A new
UnifiedQueryExecutor
interface that allows the execution of arbitrary jOOQ-SQL against an API with the same return value for all drivers! Currently there are three interfaces you can use:ClassicQueryExecutor
,CompletableFutureQueryExecutor
andRXQueryExecutor
. The following is possible now:
//first, you decide to use the classic API using JDBC
ClassicQueryExecutor queryExecutor = new JDBCClassicGenericQueryExecutor(configuration,vertx);
Future<QueryResult> queryResult = queryExecutor.query(dslContext ->
dslContext
.selectFrom(Tables.SOMETHING)
.where(Tables.SOMETHING.SOMEID.eq(something.getSomeid()))
);
//fetching values using new QueryResult-API
queryResult.map(res -> {
Integer someId = res.get(Tables.SOMETHING.SOMEID);
return someId;
});
...
//now some time in the future you decide to use the reactive driver instead
ClassicQueryExecutor queryExecutor = new ReactiveClassicGenericQueryExecutor(configuration,pgClient);
//the return value for the query didn't change!
Future<QueryResult> queryResult = queryExecutor.query(dslContext ->
dslContext
.selectFrom(Tables.SOMETHING)
.where(Tables.SOMETHING.SOMEID.eq(something.getSomeid()))
);
queryResult.map(res -> {
Integer someId = res.get(Tables.SOMETHING.SOMEID);
//hooray same API
return someId;
});
- In addition you can now obtain the
QueryExecutor
from every DAO by callingDAO.queryExecutor()
. - Move away from
GeneratorStrategies
to generate DAOs: it was a misconception to useGeneratorStrategies
to distinguish between the APIs, drivers and injection-support. Instead, there is now a Builder-API to create theVertxGenerator
of your choice. This comes in handy if you configure your jOOQ code generator programmatically. Example:
VertxGenerator vertxGenerator = VertxGeneratorBuilder
.init()
.withClassicAPI()
.withAsyncDriver()
.withGuice(true)
.build();
- Breaking changes:
- DAOs are no longer aware of
org.jooq.Configuration
, instead it is now located in theQueryExecutor
. QueryExecutor
API changed in a way, that all methods no longer accept instances oforg.jooq.Query
butFunction<DSLContext, ? extends ResultQuery<R>>
. It is no longer necessary to keep aConfiguration
object in order to execute random jOOQ SQL.JDBCQueryExecutor.execute
was renamed toJDBCQueryExecutor.executeAny
.- Upgrade from 3.x: first, change the generator- and strategy name in your code generator configuration.
Use the names as described in the module's documentation of the API and driver of your choice (e.g.
vertx-jooq-classic-async
). If you've used ownGeneratorStrategies
all have to extend now fromVertxGeneratorStrategy
. Then, update the dependencies to the code-generator and generate the code. Now you should update the vertx-jooq-YOUR_API-YOUR_DRIVER dependency. In case you've been usingQueryExecutors
you'll have to change the method calls to it as described above.
- DAOs are no longer aware of
Before you start generating code using vertx-jooq, you have to answer these questions:
- What API do you want to use? There are three options:
- a
io.vertx.core.Future
-based API. This isvertx-jooq-classic
. - a rxjava2 based API. This is
vertx-jooq-rx
. - an API that returns a vertx-ified implementation
of
java.util.concurrent.CompletableFuture
for all async DAO operations. This isvertx-jooq-completablefuture
.
- a
- How do you want to communicate with the database? There are two options:
- Using good old JDBC, check for the modules with
-jdbc
suffix. - Using this asynchronous database driver, check for
-async
modules. - Using this reactive postgres database driver, check for
-reactive
modules.
- Using good old JDBC, check for the modules with
- Do you use Guice for dependency injection?
When you made your choice, you can start to configure the code-generator. This can be either done programmatically or using a maven- / gradle-plugin (recommended way). Please check the documentation in the module of the API of your choice how to set it up:
vertx-jooq-classic-async
vertx-jooq-classic-jdbc
vertx-jooq-classic-reactive
vertx-jooq-rx-async
vertx-jooq-rx-jdbc
vertx-jooq-rx-reactive
vertx-jooq-completablefuture-async
vertx-jooq-completablefuture-jdbc
vertx-jooq-completablefuture-reactive
Once the generator is set up, it will create DAOs like in the code snippet below (classic-API, JDBC, no dependency injection):
//Setup your jOOQ configuration
Configuration configuration = ...
//setup Vertx
Vertx vertx = Vertx.vertx();
//instantiate a DAO (which is generated for you)
SomethingDao dao = new SomethingDao(configuration,vertx);
//fetch something with ID 123...
dao.findOneById(123)
.setHandler(res->{
if(res.succeeded()){
vertx.eventBus().send("sendSomething", res.result().toJson())
}else{
System.err.println("Something failed badly: "+res.cause().getMessage());
}
});
//maybe consume it in another verticle
vertx.eventBus().<JsonObject>consumer("sendSomething", jsonEvent->{
JsonObject message = jsonEvent.body();
//Convert it back into a POJO...
Something something = new Something(message);
//... change some values
something.setSomeregularnumber(456);
//... and update it into the DB
Future<Integer> updatedFuture = dao.update(something);
});
//or do you prefer writing your own type-safe SQL? Use the QueryExecutor from the DAO...
ClassicQueryExecutor queryExecutor = dao.queryExecutor();
//... or create a new one when there is no DAO around :)
queryExecutor = new JDBCClassicGenericQueryExecutor(configuration,vertx);
Future<Integer> updatedCustom = queryExecutor.execute(dslContext ->
dslContext
.update(Tables.SOMETHING)
.set(Tables.SOMETHING.SOMEREGULARNUMBER,456)
.where(Tables.SOMETHING.SOMEID.eq(something.getSomeid()))
.execute()
);
//check for completion
updatedCustom.setHandler(res->{
if(res.succeeded()){
System.out.println("Rows updated: "+res.result());
}else{
System.err.println("Something failed badly: "+res.cause().getMessage());
}
});
The generator will omit datatypes that it does not know, e.g. java.sql.Timestamp
. To fix this, you can subclass the generator, handle these types and generate the code using your generator.
See the handleCustomTypeFromJson
and handleCustomTypeToJson
methods in the AbstractVertxGenerator
or checkout the CustomVertxGenerator
from the tests.
This library comes without any warranty - just take it or leave it. Also, the author is neither connected to the company behind vertx nor the one behind jOOQ.