TeaQL vs MyBatis: an order page example
MyBatis is a productive and familiar tool for Java teams. It gives developers direct control over SQL and mapping. For many simple services, that is enough.
The pressure appears when a business page needs more than one table and more than one query shape.
Consider an order page.
The Order Page Shape
A typical order page may need:
- the order list;
- customer name;
- order status;
- line item preview;
- line item count;
- status counts for tabs;
- pagination;
- merchant or tenant filtering;
- permission-aware visibility.
With mapper-oriented persistence, this often becomes several mapper methods, XML fragments, DTO assembly, and post-query stitching.
The MyBatis Shape
A MyBatis implementation might involve:
- one SQL query for the order list;
- one query or join for customer fields;
- one query for line item previews;
- one query for counts;
- one query for grouped status statistics;
- result maps or manual DTO mapping;
- service code to assemble the final response.
That is explicit and controllable, but the business intent is spread across files.
The TeaQL Shape
TeaQL tries to express the page as one generated business request:
User userOrderInfo = Q.users()
.filterWithId(userId)
.countOrder()
.facetByOrderStatus("statusWithCount", Q.orderStatus().countOrders())
.selectOrderList(
Q.ordersWithId()
.selectOrderId()
.selectDate()
.offset(0, 10)
.selectLineItemList(
Q.lineItemsWithId().selectImageURL().limit(3)
)
.countLineItems()
)
.execute(context);
The API is still explicit, but the explicitness is at the business level:
- user;
- orders;
- status counts;
- order list;
- line items;
- pagination;
- line item count.
What TeaQL Reduces
TeaQL does not eliminate thinking. It reduces repetitive plumbing:
- mapper XML;
- duplicated DTO assembly;
- repeated relation-loading code;
- repeated count/statistics query fragments;
- stringly-typed field references;
- one-off page query services.
The generated model becomes the shared vocabulary.
Where MyBatis Still Wins
MyBatis remains a good choice when:
- a query must be hand-tuned;
- SQL is the clearest expression of the business requirement;
- the domain model is small;
- teams need exact control over vendor-specific SQL;
- generated APIs would add weight without reducing repetition.
TeaQL and MyBatis do not need to be ideological opposites. TeaQL is valuable when the business model is large enough that generated APIs reduce repeated work.
The Review Difference
In a TeaQL code review, the reviewer can ask:
- does this page select the correct relations?
- are the counts grouped correctly?
- is pagination applied at the right level?
- does the runtime context apply tenant and permission policy?
That is a higher-level review than checking XML fragments and DTO stitching.
The Short Version
MyBatis gives direct SQL control. TeaQL gives generated business APIs.
For complex business pages, TeaQL keeps page intent closer to the domain model.
