JavaStan
JavaStan

Reputation: 71

Is there a way to automatically map jOOQ records to Java records?

For this example, I am using the Sakila Sample Database.

Let's say I have a Film record as follows:

public record Film(UShort filmId, String title) {
}

If I am reading films from jOOQ, I can easily map them to Film using the following:

List<Film> films = this.context.select(Tables.FILM.FILM_ID, Tables.FILM.TITLE)
                               .from(Tables.FILM)
                               .limit(10)
                               .fetch(Records.mapping(Film::new));

Now let's say I want each film and the actors associated with it. For this, I decide to use multiset:

Set<SelectField<?>> readFields = Set.of(
    Tables.FILM.FILM_ID,
    Tables.FILM.TITLE,
    DSL.multiset(
        DSL.select(Tables.FILM_ACTOR.actor().FIRST_NAME, Tables.FILM_ACTOR.actor().LAST_NAME)
           .from(Tables.FILM_ACTOR)
           .where(Tables.FILM_ACTOR.FILM_ID.eq(Tables.FILM.FILM_ID))
        )
       .as("actors")
);

var result = this.context.select(readFields)
                         .from(Tables.FILM)
                         .limit(10)
                         .fetch();

Now that I have my results, I want to map them into a record FilmActors:

public record FilmActors(UShort filmId, String title, List<Actor> actors) {
    public record Actor(String firstName, String lastName) {
    }
}

Is there anyway to do this automatically, or with the help of a library like ModelMapper? I'm wanting to avoid rolling a custom RecordMapper if possible. Thanks!

I tried using jOOQ's built-in Records class, and tried to see if ModelMapper supports records.

Upvotes: 4

Views: 708

Answers (1)

JavaStan
JavaStan

Reputation: 71

I think found an answer here under Using ad hoc converters on nested collections. convertFrom did the trick:

Field<List<FilmActors.Actor>> actors = DSL.multiset(
                                              DSL.select(Tables.FILM_ACTOR.actor().FIRST_NAME, Tables.FILM_ACTOR.actor().LAST_NAME)
                                                 .from(Tables.FILM_ACTOR)
                                                 .where(Tables.FILM_ACTOR.FILM_ID.eq(Tables.FILM.FILM_ID))
                                          )
                                          .as("actors")
                                          .convertFrom(record -> record.map(Records.mapping(FilmActors.Actor::new)));

List<FilmActors> filmActors = this.context.select(Tables.FILM.FILM_ID, Tables.FILM.TITLE, actors)
                                          .from(Tables.FILM)
                                          .limit(10)
                                          .fetch(Records.mapping(FilmActors::new));

Upvotes: 3

Related Questions