坚信科学,分享技术

>>>尝试更加利于阅读的2014版科学院,以后都在新版上写。

rose手册第三章B节:DAO层:DAO进阶:SQLParm支持和表达式SQL

rose

3.B.1 SQLParam介绍:DAO方法传递参数

SQLParam作为DAO支持中的参数传递使者,可以传递一个常见的变量,也可以是一个自定义的对象。
比如:

  1. @SQL("insert into test (id,msg) values (:t.id,:t.msg)")  
  2.  public void insertTest(@SQLParam("t") Test test);  

上列中Test对象通过t传递到sql执行中去,并且可以分别使用其中的属性。这感觉是不是很自然?

当然,如果是一个int、long、String等自在不言中。

当是list时,会有自动的batch操作,将sql拆为多条sql执行。这个小技巧会在后面的章节里讲。平时很少用到。

3.B.2 ReturnGeneratedKeys介绍:返回刚刚插入的ID号

特别是使用mysql开发的广大劳苦大众,常常会使用到auto_increament的字段。
当一条insert语句在执行的时候,我们常常会去需要拿它的当前的自增id是多少。

  1. @ReturnGeneratedKeys  
  2. @SQL("insert into test (id,msg) values (:t.id,:t.msg)")  
  3. public int insertTest(@SQLParam("t") Test test);  

如上述代码所示,只需要加上一个@ReturnGeneratedKeys即可返回当前的id

3.B.2 表达式的支持

多变的业务需求决定了我们的sql是复杂的,需要有条件地执行。
如果每种条件都去写DAO中的SQL,那DAO的变得很大。
常常会有动态产生sql的需求。

jade支持一些常规的表达式。

语法一:常见的变量赋值
冒号(:)表示这是一个变量,比如上面的例子里的 :t.id,它会被一个值替换。

语法二:字符串连接
连续的井号(##) 表示后面的变量作字符串连接
如下例中的partition变量,还请不要误解,分表不是这样做的,下一章会介绍标准的分表设置。

  1. @SQL("SELECT user_id, device_token FROM test_##(:partition) LIMIT :limit")  
  2. public List<Test> getTests(@SQLParam("partition"int partition, @SQLParam("limit"int limit);  

语法三:条件选择

井号if(#if{})用于表示当条件满足时sql拼接。

  1. @SQL("SELECT user_id, device_token FROM test_##(:partition) #if(:user>0){ where user_id=:user } LIMIT :limit")  
  2.    public List<Test> getTestsIf(@SQLParam("partition"int partition, @SQLParam("limit"int limit, @SQLParam("user"int user);   

其他语法:还有for循环,实际使用少。
典型地,一般的select in查询,可以直接传入list,例如下例中的ids变量:

  1. @SQL("SELECT user_id, device_token FROM test_##(:partition) where user_id in(:ids)")  
  2. public List<Test> getTestsByIds(@SQLParam("partition"int partition, @SQLParam("ids") List<Integer> ids);  

文中所提及代码均在 https://github.com/XiaoMi/rose/tree/master/rose-example 提供。
常年更新版本在:https://github.com/XiaoMi/rose


原创文章如转载,请注明:转载自五四陈科学院[http://www.54chen.com]
本文链接: http://www.54chen.com/java-ee/rose-3-b.html

This entry was posted in java and tagged . Bookmark the permalink.

34 Responses to “rose手册第三章B节:DAO层:DAO进阶:SQLParm支持和表达式SQL”

  1. vincent 说:

    有没有关于事务处理的文章

  2. 小丁 说:

    求助: 我目前在用rose 的时候在jade DAO层和controller层中间做了一层service, 目前需要处理一些复杂的业务逻辑, 还要和第三方系统交互, 想请问一下你们在用的时候有没有做service,以及怎样处理异常? 看到文档中有在controller做异常处理,但是我们的业务很多不适合在controller做。

    • 54chen 说:

      我们用的时候有service,异常一般都放到controller中,如果service是面向第三方,我们有内部的通讯框架插件。

  3. xiaohuo 说:

    其实可以把rose定位于java系统里的敏捷开发,这和事务就不矛盾了。如果要给jade添加事务能力,您有什么好的方案或思路么?或是如何为rose敏捷的添加事务支持?

    • 54chen 说:

      要加jade的事务处理,你可以研究一下jdbctemplate的事务支持,大致是org.springframework.jdbc.datasource.DataSourceTransac里实现的。用得比较少,没有实测过。

  4. kingdelee 说:

    陈老师
    你好,请问一下,能否把自己写好的一段sql片段拼装进去?
    如在home中:
    String sql = "and name = 'Mr.lee' and num > 20";
    userDao.getUser(sql);

    DAO中:
    @SQL("SELECT $FIELDS FROM $TABLE WHERE 1 = 1 .... ")
    User getUser(.....);

    能否拼装进去?如何拼装?

    因为应用场景是,用户可选输入属性进行搜索。我采用陈老师中的方式
    DAO:
    @SQL("SELECT $FIELDS FROM $TABLE WHERE 1 = 1 #if(:num>0) { AND num=:num} ")
    User getUser(@SQLParam("num") long num);

    他会报BadSqlGrammarException SQLSyntaxErrorExeption Long coercion exception

    但倘若仅将#if(:num>0) 改成 #if(:num=0) 大于改成等于,则无论=后面的值是什么,总能查询出结果来,哪怕没有存有num=1,传这个num=1进去也能查出结果来...

    这是怎么回事呢?...请教一下

    • 54chen 说:

      1.拼装:
      http://www.54chen.com/rose.html
      3.B.2 表达式的支持
      语法二:字符串连接
      连续的井号(##) 表示后面的变量作字符串连接

      文档中有例子。

      2.#if(:num==0){}试试。

      • kingdelee 说:

        用 #if(:num==0){} 也会报异常
        后来一位同事告诉我用if(:num > 0, num = :num, 1)试试,我试了可以达到我想要的结果,就用这个了哈
        谢谢陈老师

  5. kingdelee 说:

    陈老师,再问一下,能直接传一个完整的sql进DAO中么?
    这个怎么写呢?

  6. xiaohuo 说:

    hi,陈老师,请教一个问题,jade能有效防止sql注入么?这方面有什么比较好的方案么?

    • 54chen 说:

      jade使用的是jdbctemplate,一般来讲,你的参数都是通过preparestatement进去的,所以完全不必要担心sql注入的问题,实际应用中,也很少有写出能够注入的代码来,除非故意制造场景。

  7. mazhen 说:

    最近使用jade发现一个问题,不知道是不是bug,就是在使用对象参数时,如果对象里面的属性为size时,sql语句便会报错。如:‘limit :1.start,:1.size’。其中start解析没有问题,而size解析失败。

    经过跟踪,是在
    net.paoding.rose.jade.statement.expression.impl.ExprResolverImpl.executeExpr(String)里的
    expr = ExpressionFactory.createExpression(builder.toString());一行报出来的。(可能是这行之前解析出的builder有问题。)
    很纠结啊。难不成这是jade的关键字不成。
    经测试讲size改成sized就没有问题了。
    鼓捣了半天,不知道有谁也遇到过这类问题。
    另,如果是bug,能解决否?

    • 54chen 说:

      不是bug。是size是java中经常出现在list等结构中的常用字,sql解析时,jade期待的是t.size()的结果。所以会解析出错。不建议你对成员变量取名为size。

  8. 风云 说:

    你好,请问下,我想在DAO里调用有输出参数的存储过程SQL应该怎么写?谢谢!

  9. 高通 说:

    支持join语句吗?多表查询,类似Hibernate那样

  10. sillycoder 说:

    陈老师,请问怎样取到update影响的行数

  11. atomic_ljz 说:

    jade能够支持存储过程调用?能否传递对象参数给存储过程?

  12. 叶良辰 说:

    chen老师,请问 那个SQL表示式的for循环语句怎么写?或者能告诉我下那个解析sql的类是那个呀?

  13. anonymous 说:

    请问rose的最新版有没有增加事务的支持呢?

  14. anping 说:

    陈老师.rose dao 不能执行存储过程吗????

  15. mr_change 说:

    你好,for就是类似于mybatis的foreach么?for的用法是什么?

Leave a Reply