If you're a Java Engineer, you probably know about Hibernate, an open-source object relation mapping (ORM) that helps map an object domain to a relational database.
jOOQ generates Java code from your database and lets you build type safe SQL queries through its fluent API.[jooq.org]
What are the features of jOOQ?
Object-oriented
jOOQ is object-oriented.
It supports lambda expressions, flow control, etc.
High performance
jOOQ has excellent performance but lacks flexibility and computing power.
jOOQ creates the SQL statements after execution and sends them to the database to perform calculations and give back the result.
This process makes jOOQ poor in flexibility.
Type-safety
jOOQ uses the Java compiler to compile SQL syntax.
Code generation
jOOQ creates Java classes from the database metadata.
Easy library import
jOOQ allows you to import external libraries easily.
IDE and debugging
jOOQ has its graphical IDE and debugging support.
What are the disadvantages of jOOQ?
Steep learning curve
Before you consider learning jOOQ, you should be comfortable with SQL.
jOOQ is straightforward when used during development.
However, it becomes complex when translating from SQL to jOOQ.
Amount of code
Since jOOQ is about SQL, it requires importing several functions.
This translates into creating a large amount of code.
How does jOOQ compare to SPL?
Even though jOOQ supports some object-oriented features, it's inconvenient to use them. SPL, however, has a more elegant syntax.
SPL is an interpreted language. The performance is slower than jOOQ, but it has stronger computing power.
SPL has built-in data processing functions, allowing higher development efficiency and lower time complexity.
SPL has an IDE suitable for data processing.
SPL has a more relaxed learning curve since it aims to simplify Java or SQL code.
SPL is less verbose than jOOQ.
Examples
Here are some examples of jOOQ syntax compared to SPL:
Read data from the database
// jOOQ
java.sql.Connection conn = DriverManager.getConnection(url, userName, password);
DSLContext context = DSL.using(conn, SQLDialect.MYSQL);
Result<OrdersRecord> R1=context.select().from(ORDERS).fetchInto(ORDERS);
// SPL
=conn=connect("mysql8")
=conn.query("select * from Orders")
=conn.query("select SellerID,Client,Amount from Orders")
Write data to the database
// jOOQ
r.setValue(ORDERS.AMOUNT,r.getValue(ORDERS.AMOUNT).doubleValue()+100);
r.update();
// SPL
conn.update(NT:T,orders)
Access a field
// jOOQ
R1.get(0).getClient();
R1.get(0).get(ORDERS.CLIENT);
// SPL
T(1).Client
T(1).field(2)
T(1).field("Client")
Grouping and aggregating
// jOOQ
context.select(ORDERS.CLIENT,year(ORDERS.ORDERDATE).as("y"),sum(ORDERS.AMOUNT).as("amt"),count(one()).as("cnt"))
.from(ORDERS)
.groupBy(ORDERS.CLIENT,year(ORDERS.ORDERDATE))
.having(field("amt").lessThan(20000)).fetch();
// SPL
Orders.groups(Client,year(OrderDate):y;sum(Amount):amt,count(1):cnt)
.select(amt<20000)
Select the top 3 elements in each group
// jOOQ
WindowDefinition CA = name("CA").as(partitionBy(ORDERS.CLIENT).orderBy(ORDERS.AMOUNT));
context.select().from(select(ORDERS.ORDERID,ORDERS.CLIENT,ORDERS.SELLERID,ORDERS.AMOUNT,ORDERS.ORDERDATE,rowNumber().over(CA).as("rn")).from(ORDERS).window(CA) ).where(field("rn").lessOrEqual(3)).fetch();
// SPL
Orders.group(Client).(~.top(3;Amount)).conj()
Calculate the maximum consecutive days that a stock keeps rising
// jOOQ
WindowDefinition woDay1 = name("woDay").as(orderBy(APPL.DAY));
Table<?>T0=table(select(APPL.DAY.as("DAY"),when(APPL.PRICE.greaterThan(lag(APPL.PRICE).over(woDay1)),0). otherwise(1).as("risingflag")).from(APPL).window(woDay1)).as("T0");
WindowDefinition woDay2 = name("woDay1").as(orderBy(T0.field("DAY")));
Table<?>T1=table(select(sum(T0.field("risingflag").cast(java.math.BigDecimal.class)).over(woDay2). as("norisingdays")).from(T0).window(woDay2)).as("T1");
Table<?>T2=table(select(count(one()).as("continuousdays")).from(T1).groupBy(T1.field("norisingdays"))).as("T2");
Result<?> result=context.select(max(T2.field("continuousdays"))).from(T2).fetch();
// SPL
APPL.sort(day).group@i(price<price[-1]).max(~.count())
P.S: in this example, jOOQ needs to calculate the number of days where the stock doesn't increase first. Then, it marks each record with a flag (risingflag
) in chronological order.
Calculate bonus according to rules
// jOOQ
Orders.forEach(r->{
Double amount=r.getValue(ORDERS.AMOUNT);
if (amount>10000) {
r.setValue(ORDERS.BONUS), amount * 0.05);
}else if(amount>=5000 && amount<10000){
r.setValue(ORDERS.BONUS),amount*0.03);
}else if(amount>=2000 && amount<5000){
r.setValue(ORDERS.BONUS),amount*0.02);
}
});
// SPL
Orders.(Bonus=if(Amount>10000,Amount*0.05,
if(Amount>5000 && Amount<10000, Amount*0.03,
if(Amount>=2000 && Amount<5000, Amount*0.02)
)))
Key Takeaways
In this article, you learned about the following:
What jOOQ is.
The language features of jOOQ.
Some disadvantages of jOOQ.
jOOQ VS SPL.
How SPL syntax is simpler than jOOQ.
If you enjoyed this article, you'll definitely benefit from subscribing to my FREE weekly newsletter, where I talk about software engineering, career development, and more. I hope to see you there.
Until next time!
🙋🏾