JOOQ 的使用 - 基于代码生成的 ORM (CRUD & DAO)
jOOQ 是基于 JDBC 之上的一个抽象层,提供了多种多样的模型来与关系型数据库进行互操作;其使用与 mybatis 和 Hibernate ORM 不同的思路来实现 对象关系映射 ORM 。
JOOQ 的使用 - 代码生成配置 (PostgreSQL & DDL Driven) 介绍了使用 jOOQ 为数据库表生成实体类代码;本篇主要介绍基于生成的关系型实体的 CRUD 和 DAO 实践。
🔗Generated Classes
本文使用了 代码生成 里面的基于 PostgreSQL 实例驱动生成的代码,代码结构如下:
├── tables
│ ├── daos
│ │ ├── AuthorDao.java
│ │ └── BookDao.java
│ ├── interfaces
│ │ ├── IAuthor.java
│ │ └── IBook.java
│ ├── pojos
│ │ ├── Author.java
│ │ └── Book.java
│ ├── records
│ │ ├── AuthorRecord.java
│ │ └── BookRecord.java
│ ├── Author.java
│ └── Book.java
├── DefaultCatalog.java
├── Indexes.java
├── Keys.java
├── Public.java
├── Sequences.java
└── Tables.java
🔗CRUD
对于设置了主键 (Primary Key) 的数据表,jOOQ 代码生成插件会为其生成一个 org.jooq.UpdatableRecord
类的子类,如为数据表 author
生成类 AuthorRecord
。对该类可以直接执行 CRUD 的操作。
final DSLContext dsl = DSL.using(SQLDialect.POSTGRES); // Only for show case // READ AuthorRecord fetched = dsl.fetchOne(Tables.AUTHOR, Tables.AUTHOR.ID.eq(1993L)); if (null == fetched) { fetched = dsl.newRecord(Tables.AUTHOR); fetched.setId(1993L); fetched.setFirstName("Elvis"); fetched.setLastName("Wang"); } fetched.setDateOfBirth(LocalDate.of(1993, 5, 25)); fetched.setYearOfBirth(1993L); // CREATE on not-existed, otherwise UPDATE fetched.store(); // DELETE fetched.delete();
如果数据表没有设置主键,则生成的类是 org.jooq.TableRecord
的子类而非 org.jooq.UpdatableRecord
的子类,也就没有对 CRUD 的支持。
🔗DAO
jOOQ 为数据表生成的 DAO 实现类实现了 org.jooq.DAO
接口,如为数据表 author
生成类 AuthorDao
,可以支持以下方法:
// <R> corresponds to the DAO's related table // <P> corresponds to the DAO's related generated POJO type // <T> corresponds to the DAO's related table's primary key type. // Note that multi-column primary keys are not yet supported by DAOs public interface DAO<R extends TableRecord<R>, P, T> { // These methods allow for inserting POJOs void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection<P> objects) throws DataAccessException; // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection<P> objects) throws DataAccessException; // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection<P> objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection<T> ids) throws DataAccessException; // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; // These methods allow for retrieving POJOs by primary key or by some other field List<P> findAll() throws DataAccessException; P findById(T id) throws DataAccessException; <Z> List<P> fetch(Field<Z> field, Z... values) throws DataAccessException; <Z> P fetchOne(Field<Z> field, Z value) throws DataAccessException; // These methods provide DAO meta-information Table<R> getTable(); Class<P> getType(); }
DAO 的用法不言自明。
完整的示例代码可以参见 jOOQ Usecases 。
以上。