V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
madworks
V2EX  ›  Java

大家帮看看这种 Java 写 sql 的代码可取吗

  •  
  •   madworks · 2020-10-27 12:10:01 +08:00 · 3775 次点击
    这是一个创建于 1523 天前的主题,其中的信息可能已经有所发展或是发生改变。

    @Override public DataListPage getDataListPageByFirstClass(DataListParams dataListParams, String firstClass, String branchStoreId) {

        String mainStoreId = BusinessUtils.getMainStoreId(branchStoreId);
    
        String listHql = CONSTRUCTOR
                + " FROM TCmsLesson cl, TCmsLessonStoreRel r"
                + " WHERE cl.firstClass = :firstClass"
                + " AND cl.isValid = 1"
                + " AND cl.id = r.lessonId"
                + " AND r.storeId in (:mainStoreId , :branchStoreId , '0000000')";
    
        String countHql = "SELECT COUNT(cl.id) FROM"
                + " TCmsLesson cl, TCmsLessonStoreRel r"
                + " WHERE cl.firstClass = :firstClass"
                + " AND cl.isValid = 1"
                + " AND cl.id = r.lessonId"
                + " AND r.storeId in (:mainStoreId , :branchStoreId , '0000000')";
    
        dataListParams.setDateParam("cl.createDate");
    
        return super.getDataListPageByHql(listHql, countHql, dataListParams, firstClass, mainStoreId, branchStoreId);
    }
    
    private List<T> listDataByHql(String hql, DataListParams dataListParams, Object... values) {
    	if (StringUtils.isNotEmpty(dataListParams.getBeginTime())
    			&& StringUtils.isNotEmpty(dataListParams.getEndTime())) {
    		hql = hql + " AND " + dataListParams.getDateParam() + " BETWEEN '" + dataListParams.getBeginTime()
    				+ "' AND '" + dataListParams.getEndTime() + "'";
    	} else if (StringUtils.isNotEmpty(dataListParams.getBeginTime())) {
    		hql = hql + " AND " + dataListParams.getDateParam() + " >= '" + dataListParams.getBeginTime() + "'";
    	} else if (StringUtils.isNotEmpty(dataListParams.getEndTime())) {
    		hql = hql + " AND " + dataListParams.getDateParam() + " <= '" + dataListParams.getEndTime() + "'";
    	}
    
    	if (StringUtils.isNotEmpty(dataListParams.getOrderBy())) {
    		hql = hql + " ORDER BY " + dataListParams.getOrderBy();
    	}
    
    	if (dataListParams.isDesc()) {
    		hql = hql + " DESC";
    	}
    
    	if (dataListParams.getPage() != null) {
    		return this.listByPage(hql, dataListParams.getPage(), values);
    	} else {
    		return dataListParams.getSize() == 0
    				? this.listByParamsAndPosition(hql, dataListParams.getStartPosition(), values)
    				: this.listBySizeAndPosition(hql, dataListParams.getSize(), dataListParams.getStartPosition(),
    						values);
    	}
    }
    
    35 条回复    2020-11-19 17:13:18 +08:00
    Kirsk
        1
    Kirsk  
       2020-10-27 12:15:54 +08:00 via Android
    罗里八嗦 直接删掉 类型控制应该在逻辑层 dao 只负责执行
    chendy
        2
    chendy  
       2020-10-27 12:18:28 +08:00
    很有毅力
    试试 Criteria ?
    geligaoli
        3
    geligaoli  
       2020-10-27 12:46:24 +08:00   ❤️ 2
    用字符串拼 sql 的,直接开
    rodrick
        4
    rodrick  
       2020-10-27 12:52:29 +08:00
    虽然很久不搞 java 你要小项目简单 sql 这么搞搞就算了,正规项目这么搞不说别的,写起来不累么,看的都累
    EscYezi
        5
    EscYezi  
       2020-10-27 12:52:58 +08:00 via iPhone
    以后维护起来很蛋疼
    wilsonWei
        6
    wilsonWei  
       2020-10-27 13:26:49 +08:00
    字符串拼接有注入风险吧,看起来也不清晰
    THESDZ
        7
    THESDZ  
       2020-10-27 13:41:44 +08:00
    如果一段代码让人看下去的欲望都没有,还是算了吧....
    THESDZ
        8
    THESDZ  
       2020-10-27 13:42:15 +08:00
    @THESDZ #7 特别复杂的业务除外(防杠)
    Resource
        9
    Resource  
       2020-10-27 13:47:14 +08:00
    不可取
    zouzou0208
        10
    zouzou0208  
       2020-10-27 13:47:38 +08:00
    这样拼接并且不做保护的话很容易注入的。在 para 里加个 or 1=1 后面就可以加东西了。
    madworks
        11
    madworks  
    OP
       2020-10-27 13:48:59 +08:00
    @THESDZ 框架层面呢,我公司用的一个中台系统 orm 框架里就是 sql 拼接的,数据层次非常多
    zouzou0208
        12
    zouzou0208  
       2020-10-27 13:51:41 +08:00
    @madworks 那样一般都有正则或者其他的保护的。
    THESDZ
        13
    THESDZ  
       2020-10-27 13:53:09 +08:00
    @madworks 框架层面的一般是基于反射或者代理等,每一个方法进行封装,查看主体逻辑的时候,配合注释(方法上的 javadoc)看起来并不会难受,而上面的代码,从列名到表名都是手敲的....
    supuwoerc
        14
    supuwoerc  
       2020-10-27 13:55:42 +08:00
    作为前端路过,刚学完预编译 sql,这样拼接字符串是不是会出现 sql 注入的问题,而且看着好累啊 =。=||
    madworks
        15
    madworks  
    OP
       2020-10-27 13:55:42 +08:00
    @THESDZ 这种代码感觉 3,4 年前 hibernate 这样写的很普遍
    THESDZ
        16
    THESDZ  
       2020-10-27 14:00:52 +08:00
    @madworks 是指题目中的代码?hibernate 了解不多,但是据我了解它的目的是让程序员不写 sql,hibernate 应该不会这么写,最起码业务内容和转 sql 是分开考虑的,不会根据逻辑拼接 sql
    fallinlovewith
        17
    fallinlovewith  
       2020-10-27 14:18:21 +08:00
    见过用 String sql = " "+ " "+ "....";
    也见过 StringBuilder sb = new StringBuilder();
    sb.append("")
    .append("")
    ......
    fengpan567
        18
    fengpan567  
       2020-10-27 14:31:54 +08:00
    这么拼接不怕 sql 注入?
    buruliu
        19
    buruliu  
       2020-10-27 14:36:26 +08:00
    hql 。
    doudou1523102
        20
    doudou1523102  
       2020-10-27 14:47:06 +08:00
    看的头痛
    joyhub2140
        21
    joyhub2140  
       2020-10-27 14:50:34 +08:00
    内部小项目这样子搞没太大问题,商业项目这样子,早晚推倒重做。
    lonelymarried
        22
    lonelymarried  
       2020-10-27 14:58:35 +08:00
    我刚学 java,如果复杂的查询不这样写,那么怎么写呢。学习一下。
    la2la
        23
    la2la  
       2020-10-27 15:04:10 +08:00
    我们公司的项目部分接口就是这么搞得,看的脑壳疼。但是领导都没说什么,我还能做啥呢
    somefree
        24
    somefree  
       2020-10-27 15:29:19 +08:00
    这一看都是上古时期的代码了, 跟我以前的公司代码有的一拼
    fatpower
        25
    fatpower  
       2020-10-27 15:33:41 +08:00   ❤️ 1
    这个不是 sql,是 hql 。
    上古时期的代码都这样
    weizhen199
        26
    weizhen199  
       2020-10-27 16:04:48 +08:00
    你们仔细看看,我咋觉得这 sql 参数化了??
    madworks
        27
    madworks  
    OP
       2020-10-27 16:21:12 +08:00
    @weizhen199 什么叫 sql 参数化
    a719031256
        28
    a719031256  
       2020-10-27 16:21:54 +08:00
    人才。。
    dyeed
        29
    dyeed  
       2020-10-27 16:22:51 +08:00
    @fatpower 需要维护丝丝诶吃( SSH )的我 o(╥﹏╥)o 了。。。。。。。。。
    aguesuka
        30
    aguesuka  
       2020-10-27 17:45:43 +08:00 via Android
    好不好不评价,给几个建议。String hql=前一句加上 // language=HQL (sql jpaql 同理)。参数使用冒号加参数名的格式,然后用 setparammap 或者 setpropsobject 设置参数的值。参数和返回值加上泛型。
    java 的 orm 包括不限于 jpa mybatis springtemplate 都不咋地,在面相对象而且自省能力这么弱的语言里发明一种代替 sql 的 dsl 是不可能的。
    我能想到的最好办法是整合项目设计的时候不考虑 sql,专门招聘一个实习生来写 dao 层。
    meepo3927
        31
    meepo3927  
       2020-10-27 17:59:16 +08:00
    嗯…… 这个换行风格,看着好难受
    akira
        32
    akira  
       2020-10-27 18:07:00 +08:00
    不可取。 现在应该都放弃这种写法了吧。 可维护性不是很好
    jin7
        33
    jin7  
       2020-10-28 00:06:34 +08:00
    看着麻烦
    Joker123456789
        34
    Joker123456789  
       2020-11-12 11:15:00 +08:00
    首先,你如果问的是把 sql 写在类里面 这种方式可不可取,那我个人认为把 sql 写类里面,和写 xml 里没啥区别, 现在都是 boot 打 jar 包,即使写在 xml 里 也是无法在线上更改的。

    无论写哪,只要牵扯到改,都要程序员改完提测 然后重新打包发布,所以写类和写 xml 已经没有本质区别了。

    所以,这种写法我个人认为完全没问题,不过肯定会有一些 盲目遵守规范的人 会说不行, 这个就不做争论了。。

    其次,如果你问的这你贴出来的这段代码有没有问题,那么其他人已经都告诉你了,你需要让代码分布的更合理一点,然后参数不要拼接,要用占位符。
    ly61
        35
    ly61  
       2020-11-19 17:13:18 +08:00
    自己写爽不爽我不知道,但是后面维护的人肯定很爽
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2597 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:54 · PVG 12:54 · LAX 20:54 · JFK 23:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.