# JaQu

## What is JaQu

JaQu stands for Java Query and allows to access databases using pure Java. JaQu replaces SQL, JDBC, and O/R frameworks such as Hibernate. JaQu is something like LINQ for Java (LINQ stands for "language integrated query" and is a Microsoft .NET technology). The following JaQu code:

    Product p = new Product();
    List<Product> soldOutProducts =
      db.from(p).where(p.unitsInStock).is(0).select();

stands for the SQL statement:

    SELECT * FROM PRODUCTS P
    WHERE P.UNITS_IN_STOCK = 0

## Advantages

Unlike to SQL, JaQu can be easily integrated in Java applications. Because JaQu is pure Java, Javadoc and auto-complete are supported. Type checking is performed by the compiler. JaQu fully protects against SQL injection.

### Why in Java?

Most people use Java in their application. Mixing Java and another language (for example Scala or Groovy) in the same application is complicated. It would be required to split the code to access the database and the application code.

## Current State

JaQu is not yet stable, and not part of the h2.jar file. However the source code is included in H2, under:

- src/test/org/h2/test/jaqu/* (samples and tests)
- src/tools/org/h2/jaqu/* (framework)

## Requirements

JaQu requires Java 1.5. Annotations are not need. Currently, JaQu is only tested with the H2 database engine, however in theory it should work with any database that supports the JDBC API.

## Example Code

    package org.h2.test.jaqu;
    import java.math.BigDecimal;
    import java.util.List;
    import org.h2.jaqu.Db;
    import static org.h2.jaqu.Function.*;

    public class Test {
       Db db;

       public static void main(String[] args) throws Exception {
           new SamplesTest().test();
       }

       public void test() throws Exception {
           db = Db.open("jdbc:h2:mem:", "sa", "sa");
           db.insertAll(Product.getProductList());
           db.insertAll(Customer.getCustomerList());
           db.insertAll(Order.getOrderList());
           testLength();
           testCount();
           testGroup();
           testSelectManyCompoundFrom2();
           testWhereSimple4();
           testSelectSimple2();
           testAnonymousTypes3();
           testWhereSimple2();
           testWhereSimple3();
           db.close();
       }

       private void testWhereSimple2() throws Exception {
           Product p = new Product();
           List<Product> soldOutProducts =
               db.from(p).
               where(p.unitsInStock).is(0).
               orderBy(p.productId).select();
       }

       private void testWhereSimple3() throws Exception {
           Product p = new Product();
           List<Product> expensiveInStockProducts =
               db.from(p).
               where(p.unitsInStock).bigger(0).
               and(p.unitPrice).bigger(3.0).
               orderBy(p.productId).select();
       }

       private void testWhereSimple4() throws Exception {
           Customer c = new Customer();
           List<Customer> waCustomers =
               db.from(c).
               where(c.region).is("WA").
               select();
       }

       private void testSelectSimple2() throws Exception {
           Product p = new Product();
           List<String> productNames =
               db.from(p).
               orderBy(p.productId).select(p.productName);
           List<Product> products = Product.getProductList();
       }

       public static class ProductPrice {
           public String productName;
           public String category;
           public Double price;
       }

       private void testAnonymousTypes3() throws Exception {
           final Product p = new Product();
           List<ProductPrice> productInfos =
               db.from(p).orderBy(p.productId).
               select(new ProductPrice() { {
                       productName = p.productName;
                       category = p.category;
                       price = p.unitPrice;
               }});
           List<Product> products = Product.getProductList();
       }

       public static class CustOrder {
           public String customerId;
           public Integer orderId;
           public BigDecimal total;
       }

       private void testSelectManyCompoundFrom2() throws Exception {
           final Customer c = new Customer();
           final Order o = new Order();
           List<CustOrder> orders =
               db.from(c).
               innerJoin(o).on(c.customerId).is(o.customerId).
               where(o.total).smaller(new BigDecimal("500.00")).
               orderBy(1).
               select(new CustOrder() { {
                   customerId = c.customerId;
                   orderId = o.orderId;
                   total = o.total;
               }});
       }

       private void testLength() throws Exception {
           Product p = new Product();
           List<Integer> lengths = db.from(p).
               where(length(p.productName)).smaller(10).
               orderBy(1).
               selectDistinct(length(p.productName));
       }

       private void testCount() throws Exception {
           long count = db.from(new Product()).selectCount();
       }

       public static class ProductGroup {
           public String category;
           public Long productCount;
       }

       private void testGroup() throws Exception {
           final Product p = new Product();
           List<ProductGroup> list =
               db.from(p).
               groupBy(p.category).
               orderBy(1).
               select(new ProductGroup() { {
                   category = p.category;
                   productCount = count();
               }});
       }

    }