zoukankan      html  css  js  c++  java
  • 像写SQL一样编写Java数据应用-TinySqlDsl

    前言
    话说企业应用,一般离不开数据库。要做数据库,可以有N种方案,比如:直接采用JDBC层自己封装下使用的,采用一些框架的,如:iBatis,Hiberate,Spring JDBC Template等等(这个太多了,因此不一一列举)的,这些方案也都在各自的领域展示了自己的特点,解决了相当部分的技术问题,并取得了相当好的应用效果。 
    但是不管是哪种方案,其优点和缺点往往也是连在一起的,究其原因是因为SQL和Java编程之间是割裂的,如果封装得不到位,做Java的人太难使用;如果封装得太多,在做一些用复杂SQL的时候又非常麻烦。比如:Hibernate就采用了封装HQL的方式来解决这方面的问题。iBatis对于SQL支持比较好,但是又会有一些割裂感,同时在解决时还要引入动态SQL来解决需要根据一些运行时条件来处理的问题,一定程度上又增加了使用的复杂度。 
    那么问题就来了,有没有更好的方式来解决数据库应用开发过程中的问题呢?究其根本原因是要如何解决数据库开发中的SQL与Java代码之间的割裂问题,如果能把这个问题解决掉,理论上会有一个不错的解。 
    我们知道SQL实际是是一种数据为领域的DSL语言,如果我们能直接在Java中编写SQL,然后执行结果就可以直接返回Java对象,这个问题不就有了良好的解决方案么? 
    TinySqlDsl解决方案
    实际上这方面已经有一些现成的解决方案,但是有的不是开源的,有的支持的还不是非常到位,因此悠然就决定尝试着写一下,写了半天时间看了看效果,详见RESTful风格的支持实践一文,内部讨论了一下,感觉还不错,于是正式决定正式花时间来编写一个TinySqlDsl,当然实际编写的时候,还是有许多的问题点的,以至于最终的风格与上面的文章还有一些不一致,当然这也是正常的,容易理解的,否则那什么也太神了。 
    我们常见的SQL语句有Select、Insert、Update、Delete,因此我们的方案中也实现了这几个语句的编写方式。 
    首先来看看看TinySqlDsl版的Dao是怎么写的。 
    第一步:定义POJO

    1. <strong>public class Custom {
    2. private String id;
    3. private String name;
    4. private int age;
    5. public String getId() {
    6. return id;
    7. }
    8. public void setId(String id) {
    9. this.id = id;
    10. }
    11. public String getName() {
    12. return name;
    13. }
    14. public void setName(String name) {
    15. this.name = name;
    16. }
    17. public int getAge() {
    18. return age;
    19. }
    20. public void setAge(int age) {
    21. this.age = age;
    22. }
    23. }
    24. </strong>
    复制代码

    第二步:定义表结构定义文件

    1. public class CustomTable extends Table {
    2. public static final CustomTable CUSTOM = new CustomTable();
    3. public final Column ID = new Column(this, "id");
    4. public final Column NAME = new Column(this, "name");
    5. public final Column AGE = new Column(this, "age");
    6. private CustomTable() {
    7. super("custom");
    8. }
    9. }
    复制代码


    第三步:编写DAO类

    1. public class CustomDao {
    2. private DslSession dslSession;
    3. public DslSession getDslSession() {
    4. return dslSession;
    5. }
    6. public void setDslSession(DslSession dslSession) {
    7. this.dslSession = dslSession;
    8. }
    9. public void insertCustom(Custom custom) {
    10. dslSession.execute(
    11. insertInto(CUSTOM).values(
    12. CUSTOM.ID.value(custom.getId()),
    13. CUSTOM.NAME.value(custom.getName()),
    14. CUSTOM.AGE.value(custom.getAge())
    15. )
    16. );
    17. }
    18. public void updateCustom(Custom custom) {
    19. dslSession.execute(
    20. update(CUSTOM).set(
    21. CUSTOM.NAME.value(custom.getName()),
    22. CUSTOM.AGE.value(custom.getAge())).where(
    23. CUSTOM.ID.eq(custom.getId())
    24. )
    25. );
    26. }
    27. public void deleteCustom(String id) {
    28. dslSession.execute(
    29. delete(CUSTOM).where(
    30. CUSTOM.ID.eq(id)
    31. )
    32. );
    33. }
    34. public Custom getCustomById(String id) {
    35. return dslSession.fetchOneResult(
    36. selectFrom(CUSTOM).where(
    37. CUSTOM.ID.eq(id)
    38. )
    39. , Custom.class);
    40. }
    41. public List<Custom> queryCustom(Custom custom) {
    42. return dslSession.fetchList(
    43. selectFrom(CUSTOM).where(
    44. and(
    45. CUSTOM.ID.eq(custom.getId()),
    46. CUSTOM.NAME.equal(custom.getName()),
    47. CUSTOM.AGE.equal(custom.getAge())
    48. )
    49. )
    50. , Custom.class);
    51. }
    52. }
    复制代码


    看了上面的示例,会不会感觉有点奇怪,怎么可以这么写?呵呵,先别着急了解实际的实现机理,我们先品味一下这种DSL风格的数据库编写方式,嗯嗯,具体的来说就是像写SQL一样的方式来写SQL。

  • 相关阅读:
    RocketMQ源码分析:(二)消息发送的三种方式
    LTS本地搭建详述
    Mac端解决(含修改8.0.13版的密码):Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
    flink入门:01 构建简单运行程序
    rocketmq控制台搭建(rocketmq-console)
    在consul上注册web服务
    将filenames里的每个字符串输出到out文件对象中注意行首的缩进
    spidermark sensepostdata ntp_monlist.py
    HTTP Error 403没有了,但是中文全都是乱码。又是怎么回事?
    original.txt和提交的页面输出的文字的混合文件
  • 原文地址:https://www.cnblogs.com/j2eetop/p/4612650.html
Copyright © 2011-2022 走看看