Java类中的SQL代码

Gen*_*diy 11 java sql integration

我们当前的项目不使用Hibernate(出于各种原因),我们使用Spring的SimpleJdbc支持来执行所有数据库操作.我们有一个实用程序类,它抽象所有CRUD操作,但使用自定义SQL查询执行复杂操作.

目前,我们的查询作为字符串常量存储在服务类本身中,并被提供给由SimpleJdbcTemplate执行的实用程序.我们陷入僵局,可读性必须与可维护性相平衡.类本身内部的SQL代码更易于维护,因为它驻留在使用它的代码中.另一方面,如果我们将这些查询存储在外部文件(平面或XML)中,与转义的java字符串语法相比,SQL本身将更具可读性.

有谁遇到过类似的问题?什么是良好的平衡?您在哪里将自定义SQL保留在项目中?

示例查询如下:

private static final String FIND_ALL_BY_CHEAPEST_AND_PRODUCT_IDS = 
"    FROM PRODUCT_SKU T \n" +
"    JOIN \n" +
"    ( \n" +
"        SELECT S.PRODUCT_ID, \n" +
"               MIN(S.ID) as minimum_id_for_price \n" +
"          FROM PRODUCT_SKU S \n" +
"         WHERE S.PRODUCT_ID IN (:productIds) \n" +
"      GROUP BY S.PRODUCT_ID, S.SALE_PRICE \n" +
"    ) FI ON (FI.PRODUCT_ID = T.PRODUCT_ID AND FI.minimum_id_for_price = T.ID) \n" +
"    JOIN \n" +
"    ( \n" +
"        SELECT S.PRODUCT_ID, \n" +
"               MIN(S.SALE_PRICE) as minimum_price_for_product \n" +
"          FROM PRODUCT_SKU S \n" +
"         WHERE S.PRODUCT_ID IN (:productIds) \n" +
"      GROUP BY S.PRODUCT_ID \n" +
"    ) FP ON (FP.PRODUCT_ID = T.PRODUCT_ID AND FP.minimum_price_for_product = T.sale_price) \n" +
"WHERE T.PRODUCT_ID IN (:productIds)";
Run Code Online (Sandbox Code Playgroud)

这是在平面SQL文件中的样子:

--namedQuery: FIND_ALL_BY_CHEAPEST_AND_PRODUCT_IDS
FROM PRODUCT_SKU T 
JOIN 
( 
    SELECT S.PRODUCT_ID, 
           MIN(S.ID) as minimum_id_for_price 
      FROM PRODUCT_SKU S 
     WHERE S.PRODUCT_ID IN (:productIds) 
  GROUP BY S.PRODUCT_ID, S.SALE_PRICE 
) FI ON (FI.PRODUCT_ID = T.PRODUCT_ID AND FI.minimum_id_for_price = T.ID) 
JOIN 
( 
    SELECT S.PRODUCT_ID, 
           MIN(S.SALE_PRICE) as minimum_price_for_product 
      FROM PRODUCT_SKU S 
     WHERE S.PRODUCT_ID IN (:productIds) 
  GROUP BY S.PRODUCT_ID 
) FP ON (FP.PRODUCT_ID = T.PRODUCT_ID AND FP.minimum_price_for_product = T.sale_price) 
WHERE T.PRODUCT_ID IN (:productIds)
Run Code Online (Sandbox Code Playgroud)

Bil*_*ard 8

我将SQL作为两个字符串存储在Java类中,并作为在运行时加载的单独文件存储.我非常喜欢后者有两个原因.首先,代码更具可读性.其次,如果将SQL存储在单独的文件中,则可以更容易地单独测试SQL.除此之外,在SQL中使用比我更好的人来帮助我查询它们在单独的文件中时更容易.


Ste*_* B. 5

我也遇到过这种情况,目前出于同样的原因 - 一个基于spring jdbc的项目.我的经验是,尽管在sql本身中拥有逻辑并不是很好,但实际上并没有更好的地方,而且放入应用程序代码比使用db做得慢,而且不一定更清楚.

我见过的最大的陷阱是sql开始在整个项目中扩散,有多种变化."从FOO获得A,B,C"."从Foo获得A,B,C,E",等等.这种扩散特别有可能是因为项目达到一定的临界质量 - 它可能看起来不像10个查询的问题,但是当整个项目中分散了500个查询时,要弄清楚你是否已经做了一些事情变得更加困难.提取基本的CRUD操作可以让您领先于游戏.

最佳解决方案AFAIK将与编码的SQL严格一致 - 经过评论,测试并保持一致.我们的项目有50行未注释的SQL查询.他们的意思是什么?谁知道?

对于外部文件中的查询,我看不出这个问题 - 你仍然只是依赖于SQL,除了保持sql不在类中的(可疑的)美学改进之外,你的类是仍然只是依赖于sql -.eg你通常将资源分开以获得插件替换资源的灵活性,但你无法插入替换的sql查询,因为它会改变类的语义或不工作在所有.所以这是一个虚幻的代码清洁.