/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Other licenses: * ----------------------------------------------------------------------------- * Commercial licenses for this work are available. These replace the above * ASL 2.0 and offer limited warranties, support, maintenance, and commercial * database integrations. * * For more information, please visit: http://www.jooq.org/licenses * * * * * * * * * * * * * */ package org.jooq.example.javaee.controller; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toMap; import static org.jooq.SQLDialect.H2; import static org.jooq.SortOrder.ASC; import static org.jooq.example.db.h2.tables.Author.AUTHOR; import static org.jooq.example.db.h2.tables.Book.BOOK; import java.io.Serializable; import java.util.Map; import java.util.stream.Stream; import javax.ejb.EJB; import javax.enterprise.context.SessionScoped; import javax.inject.Named; import org.jooq.Field; import org.jooq.Record; import org.jooq.Result; import org.jooq.SortField; import org.jooq.Table; import org.jooq.TableField; import org.jooq.UpdatableRecord; import org.jooq.example.db.h2.tables.Author; import org.jooq.example.db.h2.tables.records.AuthorRecord; import org.jooq.example.db.h2.tables.records.BookRecord; import org.jooq.example.javaee.ejb.LibraryEJB; import org.jooq.impl.DSL; /** * A bean to be used from JSF pages. * <p> * The bean is session scoped such that we can have session-based caches of * database content such as authors or books in this bean. In this simple * example, we haven't gone into concurrency situations where multiple sessions * update the library database at the same time, in case of which we might need * to turn on optimistic locking in jOOQ. * * @author Lukas Eder */ @Named("library") @SessionScoped public class Library implements Serializable { private static final long serialVersionUID = 1L; @EJB private LibraryEJB ejb; // Various caches from the DB // ------------------------------------------------------------------------- /** * An empty {@link AuthorRecord} that can be used to insert new authors. */ private AuthorRecord newAuthor; /** * An empty {@link BookRecord} that can be used to insert new books. */ private BookRecord newBook; /** * The reference to the {@link Record} that is currently being edited. */ private Record edit; /** * The sort field for each {@link Table}. */ private Map<Table<?>, SortField<?>> sort = Stream.of(AUTHOR.ID, BOOK.ID).collect( toMap(f -> f.getTable(), f -> f.asc())); /** * A cache of all {@link AuthorRecord}s currently in the database. */ private Result<AuthorRecord> authors; /** * A copy of {@link #authors} that is always sorted alphanumerically. */ private Result<AuthorRecord> authorsAlphanumeric; /** * A cache of all {@link BookRecord}s currently in the database. */ private Result<BookRecord> books; // Data access methods // ------------------------------------------------------------------------- public Result<AuthorRecord> getAuthors() { if (authors == null) authors = ejb.fetchAuthors(sort.get(AUTHOR)); return authors; } public Result<AuthorRecord> getAuthorsAlphanumeric() { if (authorsAlphanumeric == null) { authorsAlphanumeric = DSL.using(H2).newResult(AUTHOR); authorsAlphanumeric.addAll(getAuthors()); authorsAlphanumeric.sortAsc(comparing(a -> a.getFirstName() + " " + a.getLastName())); } return authorsAlphanumeric; } public Map<Integer, AuthorRecord> getAuthorById() { return getAuthors().intoMap(AUTHOR.ID); } public Result<BookRecord> getBooks() { if (books == null) books = ejb.fetchBooks(sort.get(BOOK)); return books; } public AuthorRecord getNewAuthor() { if (newAuthor == null) newAuthor = DSL.using(H2).newRecord(AUTHOR); return newAuthor; } public BookRecord getNewBook() { if (newBook == null) newBook = DSL.using(H2).newRecord(BOOK); return newBook; } // UI state methods // ------------------------------------------------------------------------- /** * The record being edited. */ public Record getEdit() { return edit; } /** * A map containing <code>column name -> column</code> pairs of the * {@link Author} table. */ public Map<String, Field<?>> getAuthorColumns() { return getColumns(AUTHOR); } /** * A map containing <code>column name -> column</code> pairs of the * {@link Author} table. */ public Map<String, Field<?>> getBookColumns() { return getColumns(BOOK); } /** * Get a map containing <code>table name -> sort field</code> pairs. */ public Map<String, SortField<?>> getSort() { return sort.entrySet().stream().collect(toMap(e -> e.getKey().getName(), e -> e.getValue())); } private Map<String, Field<?>> getColumns(Table<?> t) { return Stream.of(t.fields()).collect(toMap(f -> f.getName(), f -> f)); } private void reset() { authors = null; authorsAlphanumeric = null; books = null; edit = null; } // Actions // ------------------------------------------------------------------------- /** * Sort a table by a new field. */ public void sort(TableField<?, ?> field) { SortField<?> previous = sort.get(field.getTable()); sort.put(field.getTable(), ! previous.getName().equals(field.getName()) ? field.asc() : previous.getOrder() == ASC ? field.desc() : field.asc() ); reset(); } /** * Mark a record as the one being currently edited. */ public void edit(UpdatableRecord<?> record) { edit = record; } /** * Save a record back to the database. */ public void save(UpdatableRecord<?> author) { ejb.store(author); reset(); } /** * Delete a record from the database. */ public void delete(UpdatableRecord<?> author) { ejb.delete(author); reset(); } }