15

I was wondering if there is any library that can be used to represent SQL queries as objects in Java.

In the code I have plenty of static variables of type java.lang.String that are hand written SQL queries. I would be looking for library having a nice fluent API that allows me to represent the queries as objects rather than strings.

Example:

Query q = select("DATE", "QUOTE")
  .from("STOCKMARKET")
  .where(eq("CORP", "?"))
  .orderBy("DATE", DESC);
Tomasz Błachowicz
  • 5,731
  • 9
  • 41
  • 47

7 Answers7

13

Querydsl supports querying on SQL, JPA and JDO backends.

The example above becomes :

query.from(stockmarket).where(stockmarket.corp.eq(someVar))
    .orderBy(stockmarket.date.desc())
    .list(stockmarket.date, stockmarket.quote);

Querydsl uses code generation via APT to mirror an SQL schema to Java query types. This way the queries are fully type-safe (or "schema-compliant" with SQL).

I am the maintainer of Querydsl, so this answer is biased.

I published a comparison of Querydsl to other frameworks here.

Timo Westkämper
  • 21,824
  • 5
  • 78
  • 111
8

These are some good proprietary libraries to create typesafe SQL queries dynamically

Apart from the above, there is always

  • Hibernate/JPA CriteriaQuery
  • MyBatis

Your example in jOOQ:

create.select(DATE, QUOTE)
      .from(STOCKMARKET)
      .where(CORP.equal(123))
      .orderBy(DATE.desc());
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
7

http://www.hibernate.org/ Probably most powerfull ORM library for Java. It can do much more then just simple query mapping. So you can easily implement it somwhere else in your application. For your case it can be done somehow like that:

public class LookupCodeName
{
    private String code;
    private String name;

 /*... getter-setters ... */
}

public class someBL {

public List<LookupCodeName> returnSomeEntity() {
      SQLQuery sqlQuery =  (SQLQuery)((HibernateSession)em).getHibernateSession()
                        .createSQLQuery( "SELECT st.name as name, st.code as code FROM someTable st")
                        .addScalar("code")
                        .addScalar("name")
.setResultTransformer(Transformers.aliasToBean(LookupCodeName.class));
    }
return (List<LookupCodeName>)sqlQuery.list();
}
Vanger
  • 316
  • 4
  • 10
  • Yeah, I know Hibernate, but in your example there is still hardcoded SQL represented as string ("SELECT st.name as name, st.code as code FROM someTable st"). Maybe my question wasn't clear enough, but I wanted to replace string queries with object representation of those rather than employ powerful framework to execute queries. – Tomasz Błachowicz May 05 '09 at 15:49
  • Pregzt, you might want to take a look at Hibernate Criterias – Il-Bhima May 06 '09 at 07:33
  • I think a criteria API pulls in the wrong direction from having a SQL builder API. On my current project, the original (and long gone) developers used a criteria API, and the current team hates it. We can get a DAO method done using native SQL in half the time it takes to write the criteria API, because the we often end up looking at the SQL the criteria API generates to verify its correctness. If you know the correct SQL already, why count on a SQL generator? – Alan May 15 '09 at 04:15
  • If you know the correct SQL already, why count on a SQL generator? All your comment based at this statement. But why'd you think you "know a correct SQL"? Just some thing, hibernate stands at: 1.The sql can be too complex to write it manyally.(Complex entity relations for example) 2.If you change entity - you do not need to change criteria for new correct data mapping. 3.Do you know on which database your application will be working? Hardcoded SQL kills some independencie. – Vanger May 15 '09 at 08:47
  • The example above is using normal SQL which is bad because it usually means that your app just became dependent on one specific SQL engine as opposed to being able to run on any DB back-end. Instead, it is suggested to use HQL (Hibernate Query Language) which gets translated to SQL under-the-hood. This approach still uses strings however so refactorings can break stuff. I get around this by using a good IDE (IntelliJ) which has HQL support for its refactorings. – Jesse Webb Apr 12 '12 at 19:20
7

Jequel looks pretty nifty: http://www.jequel.de/

It uses a fluent interface, so it's easy to read, almost like natural SQL (from the docs):

SqlString sql = select(ARTICLE.OID)
               .from(ARTICLE, ARTICLE_COLOR)
               .where(ARTICLE.OID.eq(ARTICLE_COLOR.ARTICLE_OID)
               .and(ARTICLE.ARTICLE_NO.is_not(NULL)));

It also supports executing queries against a DataSource with parameters, so it handles creation of parameterized queries as well.

matt
  • 9,113
  • 3
  • 44
  • 46
  • Looks good. That is something like I was looking for. Cheers! – Tomasz Błachowicz May 15 '09 at 11:56
  • Nice! Don't forget to come back and post your findings. I only found out about it a few days ago, and I haven't had a chance to use it a lot yet, but I plan to in the future. – matt May 15 '09 at 14:30
  • I had contacted the developer of Jequel about a year ago. This project seems to have gone in maintenance mode in 2008... – Lukas Eder Jul 03 '11 at 20:26
2

Apache Empire-db is a relational database abstraction layer and data persistence component that allows developers to take a much more SQL-centric approach in application development than traditional Object-relational mapping frameworks (ORM).

More here : https://empire-db.apache.org/

Quaere

http://xircles.codehaus.org/projects/quaere

Barun
  • 1,520
  • 2
  • 12
  • 18
Sake
  • 4,033
  • 6
  • 33
  • 37
  • Is quaere active project? There is very little on their website. – Tomasz Błachowicz May 05 '09 at 15:50
  • I'm not quaere user in general. Just remember its as one of java-can-have-linq hype years ago. From the mail-list archive suggest that the project is not very active indeed. FWIW, browsing through the mail list show me some similar projects you may want to take a peek. JaQu (http://www.h2database.com/html/jaqu.html) The bottom of the page also reference so some other related projects – Sake May 08 '09 at 04:23
1

If you don't want to map string queries, then you must annotate your class as entity and bind it with table then you can use hibernate or java persistance. Example will be too complex though. But, at the end your query will transform to something like this:

find list of entities:

 Criteria c = createCreteria(entityManager, StockMarket.class);
    // you can add "where" clause by using c.add(Restrictions); 
   // like this: c.add(Restrictions.ilike("name", "%somename%"); where "name" is your entity's field
     List<StockMarket> smList = c.list();

find object by id:

 StockMarket sm  = entityManager.find(StockMarket.class, id);
Vanger
  • 316
  • 4
  • 10
0

You can use the naskarlab/fluent-query:

https://github.com/naskarlab/fluent-query

Example:

@Test
public void testSelect() {
    String expected = "select e0.* from Customer e0";

    String actual = new QueryBuilder()
        .from(Customer.class)
        .to(new NativeSQL())
        .sql()
        ;

    Assert.assertEquals(expected, actual);
}

You can see more examples in unit tests of the project:

https://github.com/naskarlab/fluent-query/blob/master/src/test/java/com/naskar/fluentquery/TestNativeSimpleConventionQueryTest.java

rafaelnaskar
  • 619
  • 6
  • 11