11

I'm not looking for a persistence layer like Hibernate, I just want to generate SQL-strings and they should be compatible with PreparedStatement. I've tried libraries such as Squiggle, but it only supports SELECT, I would also like to generate insert and updates. An ideal usage would be something like:

generateInsertOn("myTable").addValue("value1").addValue("value2").generate();

that would generate this string:

"INSERT INTO myTable (value1, value2) VALUES(?, ?)"

I know that there exists questions that are a lot like mine, such as this, but they don't quite ask the same thing as I do.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
pgsandstrom
  • 14,361
  • 13
  • 70
  • 104
  • 1
    If you already know that there are similar questions, then it's *great* that you tell us about them. But telling us **why** these questions are not what you want would be even better! – Joachim Sauer Aug 08 '11 at 13:58
  • What is your problem in writing it yourself? – user unknown Aug 08 '11 at 14:00
  • 2
    whats the problem with hibernate, its great ... – NimChimpsky Aug 08 '11 at 14:01
  • Joachim, sorry: The person I linked was satisfied with finding out about PreparedStatement. I would still like a cleaner way to write my statements, because it gets to hard to read something like c.prepareStatement("UPDATE "+MY_TABLE+" SET "+VALUE_5+"=? WHERE "+VALUE_3+"=?"); with all the syntax that is involved in string concatination. – pgsandstrom Aug 08 '11 at 14:03
  • user_unknown, it is completely redundant to write my own library if some genious already has written an optimized and tested library. NimChimpsky, I think hibernate sucks for a number of reasons, to explain why is not within the frame of this question :P – pgsandstrom Aug 08 '11 at 14:05
  • possible duplicate of [Is there any good dynamic SQL builder library in Java?](http://stackoverflow.com/questions/5620985/is-there-any-good-dynamic-sql-builder-library-in-java) – Vineet Reynolds Aug 08 '11 at 14:17
  • 1
    @NimChimpsky, I don't think Hibernate is up for the job if you want to have full control over the SQL your render... – Lukas Eder Aug 09 '11 at 06:37
  • @Lukas Eder. THe question is why do you want full control. I hate writing sql. Hibernate has been up to the job in all the enterprises I have worked at. – NimChimpsky Aug 09 '11 at 07:19
  • 2
    @NimChimpsky: Hibernate is good for many purposes, but not when you want to control your SQL. In many RDBMS and large-scale systems, if you don't control your SQL, then you're doomed. Think of adding hints to Oracle queries, or fine-tuning your nested `LEFT OUTER JOIN` expressions, integrating stored procedures, etc, etc. But we don't know what the OP intends, so let's not start this discussion... – Lukas Eder Aug 09 '11 at 07:27
  • @Lukas Eder "so let's not start this discussion." but I think you just did :-) You can use named and/or native queries as part of hibernate if you really must control yr sql to that extreme. – NimChimpsky Aug 09 '11 at 08:22
  • @NimChimpsky: ;-) With named/native queries, you're back to the OP's original question of how to avoid string concatenation... – Lukas Eder Aug 09 '11 at 08:29

3 Answers3

14

For arbitrary SQL, use jOOQ. jOOQ currently supports SELECT, INSERT, UPDATE, DELETE, TRUNCATE, and MERGE. You can create SQL like this:

// Since you're not executing the SQL, set connection to null
Connection connection = null;
Factory create = new MySQLFactory(connection);
String sql1 = create.select(A, B, C)
                    .from(MY_TABLE)
                    .where(A.equal(5))
                    .and(B.greaterThan(8))
                    .getSQL();

String sql2 = create.insertInto(MY_TABLE)
                    .values(A, 1)
                    .values(B, 2)
                    .getSQL();

String sql3 = create.update(MY_TABLE)
                    .set(A, 1)
                    .set(B, 2)
                    .where(C.greaterThan(5))
                    .getSQL();

The supported syntax is quite rich. You will also find support for clauses such as ON DUPLICATE KEY UPDATE, FOR UPDATE, LOCK IN SHARE MODE, etc.

For more details, see

http://www.jooq.org

(Disclaimer, I work for the company behind jOOQ)

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
3

You should definitively take a look at SQLBuilder. It allows simple, yet complete, SQL generation using a very fluent API.

Riduidel
  • 22,052
  • 14
  • 85
  • 185
  • Is SQLBuilder still active? There don't seem to be a lot of updates in recent history... https://sourceforge.net/projects/openhms/files/sqlbuilder/ – Lukas Eder Aug 09 '11 at 06:35
  • Does it work? I mean, I don't know, I've not used it. But if it works, who cares if it's active? – Will Hartung Aug 09 '11 at 06:37
  • 1
    Well it depends, if the OP is looking for a tool for quick-and-dirty jobs, or if he needs to live with this decision for another while. Take Xalan, for instance. It works very well but it is not at all active. There are some important open issues that will probably never be addressed... :-/ – Lukas Eder Aug 09 '11 at 07:17
  • @Will_Hartung Oh yes it do work, i use it for a migration tool that is used on a weekly basis (thanks to Hudson). – Riduidel Aug 09 '11 at 07:56
  • 1
    @Lukas_Eder Are you talking about Xalan or SQLBuilder here ? I understand you want to defend JOOQ, as you're the code author (a thing I absolutely don't want to minimize), but I don't find very good policy to immediatly dismiss other frameworks on unclear issues (in other words, if you find SQLBuilder misses some important points, write them down or don't talk about them, but please don't say they have bugs, as I think you also have in JOOQ). – Riduidel Aug 09 '11 at 07:59
  • @Riduidel: I think you got me wrong. I was just asking about whether it is still active, because I didn't know the tool and I was wondering only about its activeness. And then I gave an example about why I think this is important to Will Hartung. There was no judgement in my words... What made you think so? – Lukas Eder Aug 09 '11 at 08:56
  • @Lukas_Eder "There are some important open issues that will probably never be addressed... :-/" This sentence is, to my utterly negative French mind (we are all desperatly wanting to put our grain of salt in each and every covnersation), worded in a way that may indicate that SQLBuilder has some issues, which I found not really fair. Anyway, as it is not your goal, please pardon me. – Riduidel Aug 09 '11 at 09:15
  • 1
    Haha, you French guys :-) so, now I understand. I was actually referring to Xalan. The latest release was in [2007](http://issues.apache.org/jira/browse/XALANJ#selectedTab=com.atlassian.jira.plugin.system.project%3Aversions-panel). So I considered it inactive. – Lukas Eder Aug 09 '11 at 11:24
  • the sqlbuilder project is alive and well. lack of bug fixes doesn't mean the project is dead, just means a lack of bugs! – jtahlborn Jun 29 '12 at 17:44
  • This is the best answer for me. Now in 2016 this project is alive and regularly released, it's open source and good. We chose it for some tasks in our real-world medical applications. – ForNeVeR Mar 19 '16 at 04:09
0

Going out on a limb here, have you considered iBatis? It's a real down to earth query mapping framework (I hesitate to call it an ORM framework somehow). You have to create XML files like this one:

<mapper namespace="org.mybatis.jpetstore.persistence.ProductMapper">    
  <cache />    
  <select id="getProduct" parameterType="string" resultType="Product">
    SELECT
      PRODUCTID,
      NAME,
      DESCN as description,
      CATEGORY as categoryId
    FROM PRODUCT
    WHERE PRODUCTID = #{productId}
  </select>   
</mapper>

which wires up a mapper like this one:

public interface ProductMapper {
  Product getProduct(String productId);
}

Which allows you to access data from services like this:

  @Autowired
  private ProductMapper productMapper;  

  public Product getProduct(String productId) {
    return productMapper.getProduct(productId);
  }

Which you can wire up with Spring:

<!-- enable autowire -->
<context:annotation-config />

<!-- enable transaction demarcation with annotations -->
<tx:annotation-driven />

<!-- define the SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="typeAliasesPackage" value="org.mybatis.jpetstore.domain" />
</bean>

<!-- scan for mappers and let them be autowired -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="org.mybatis.jpetstore.persistence" />
</bean>

See also the full petstore example.

I'm not an uniquivocal fan of iBatis but it might fit your needs in this specific case.

Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60