jOOQの紹介
@chipstar_light
• 皆さんが現場で使っているのはORMですか?
• Hibernate?Doma?MyBatis?

その他のJPA実装?
• Object Mappingを有効活用できてない
• トランザクションスクリプトだし…
• Smart UIだし…
• DTOとか、Modelとかないし…
• 良くてもViewModel
• BeanUtilsレベルで問題ない
• 既にあるテーブルでなんとかしないといけない
• レガシーシステムだし…
• 他システムの連携が多くて…
• オブジェクトモデルとのミスマッチが…
• チューニングできるレベルのSQLを扱いたい
• 自由なjoin、union、procedure、

insert into select、sub query、etc…
jOOQ
• そんな人のためのデータベースアクセスライブラリ
• http://www.jooq.org/
• jOOQ generates Java code from your
database and lets you build typesafe SQL
queries through its fluent API.
• ただし!使った事無いです…。詳しくはご自分で。
jOOQ特徴
• Database First
• 既にあるテーブルスキーマから始めます
• Typesafe SQL
• タイプセーフに流れるインタフェースでSQL書けます
• Code Generation
• マッピング定義やモデル、ActiveRecordなどを自動生成
• スキーマはJavaクラスで定義
create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
.from(AUTHOR)
.join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID))
.where(BOOK.LANGUAGE.eq("DE"))
.and(BOOK.PUBLISHED.gt(date("2008-01-01")))
.groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
.having(count().gt(5))
.orderBy(AUTHOR.LAST_NAME.asc().nullsFirst())
.limit(2)
.offset(1)
.forUpdate()
.of(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME,
COUNT(*)
FROM AUTHOR
JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID
WHERE BOOK.LANGUAGE = 'DE'
AND BOOK.PUBLISHED > DATE '2008-01-01'
GROUP BY AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME
HAVING COUNT(*) > 5
ORDER BY AUTHOR.LAST_NAME ASC NULLS FIRST
LIMIT 2
OFFSET 1
FOR UPDATE
OF AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME
SQLとDSLの対比
コードはjOOQ公式サイトから引用
引用:jOOQ http://www.jooq.org/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/jooq-spring.xml"})
public class QueryTest {
@Autowired
DSLContext create;
@Test
public void testJoin() throws Exception {
// All of these tables were generated by jOOQ's Maven plugin
Book b = BOOK.as("b");
Author a = AUTHOR.as("a");
BookStore s = BOOK_STORE.as("s");
BookToBookStore t = BOOK_TO_BOOK_STORE.as("t");
Result<Record3<String, String, Integer>> result =
create.select(a.FIRST_NAME, a.LAST_NAME, countDistinct(s.NAME))
.from(a)
.join(b).on(b.AUTHOR_ID.equal(a.ID))
.join(t).on(t.BOOK_ID.equal(b.ID))
.join(s).on(t.BOOK_STORE_NAME.equal(s.NAME))
.groupBy(a.FIRST_NAME, a.LAST_NAME)
.orderBy(countDistinct(s.NAME).desc())
.fetch();
assertEquals(2, result.size());
assertEquals("Paulo", result.getValue(0, a.FIRST_NAME));
assertEquals("George", result.getValue(1, a.FIRST_NAME));
assertEquals("Coelho", result.getValue(0, a.LAST_NAME));
assertEquals("Orwell", result.getValue(1, a.LAST_NAME));
assertEquals(Integer.valueOf(3), result.getValue(0, countDistinct(s.NAME)));
assertEquals(Integer.valueOf(2), result.getValue(1, countDistinct(s.NAME)));
}
}
SELECT
コードサンプル
コードはjOOQ公式サイトから引用
引用:jOOQ http://www.jooq.org/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/jooq-spring.xml"})
@TransactionConfiguration(transactionManager="transactionManager")
public class TransactionTest {
@Autowired DSLContext dsl;
@Autowired DataSourceTransactionManager txMgr;
@Autowired BookService books;
!
@After
public void teardown() {
// Delete all books that were created in any test
dsl.delete(BOOK).where(BOOK.ID.gt(4)).execute();
}
!
@Test
public void testExplicitTransactions() {
boolean rollback = false;
TransactionStatus tx = txMgr.getTransaction(new DefaultTransactionDefinition());
try {
// This is a "bug". The same book is created twice, resulting in a
// constraint violation exception
for (int i = 0; i < 2; i++)
dsl.insertInto(BOOK)
.set(BOOK.ID, 5)
.set(BOOK.AUTHOR_ID, 1)
.set(BOOK.TITLE, "Book 5")
.execute();
}
catch (DataAccessException e) {
txMgr.rollback(tx);
}
}
INSERT
コードサンプル
コードはjOOQ公式サイトから引用
引用:jOOQ http://www.jooq.org/
皆さんも是非試してみてくだ
さい!

jOOQの紹介