如何防止sql中in子句中的空列表错误?

时间:2018-01-25 20:52:31

标签: sql database scala anorm

我们在代码库中遇到的一个常见问题是,在in子句中使用列表之前,人们忘记检查列表是否为空。

例如(在带有Anorm的Scala中):

def exists(element: String, list: List[String]): Boolean =
  SQL("select {element} in {list} as result")
    .on('element -> element, 'list -> list)
    .as(SqlParser.bool("result").single)

只要列表至少包含一个元素,此代码就能很好地工作。

如果它有0个元素,则会出现语法错误,如果您习惯使用其他允许此空列表大小写的编程语言,则会很奇怪。

所以,我的问题是:防止此错误发生的最佳方法是什么?

最初,我们这样做了:

def exists(element: String, list: List[String]): Boolean =
  if (list.nonEmpty) {
    SQL("select {element} in {list} as result")
      .on('element -> element, 'list -> list)
      .as(SqlParser.bool("result").single)
  } else {
    false
  }

这非常有效,并且具有额外的优势,即它根本不会访问数据库。

不幸的是,我们不记得每次都这样做,似乎每月1-2次我们正在解决与此相关的问题。

我们提出的替代解决方案是使用NonEmptyList类而不是标准List。该类必须至少有一个元素。这种方式非常好,但是人们并不总是习惯使用这个课程。

所以我想知道是否有一种我错过的方法可以更好地防止这种类型的错误?

2 个答案:

答案 0 :(得分:0)

你的问题是一个封装问题:Anorm API就像一个明火,人们可以燃烧自己。如果你只依靠人们采取预防措施,有人会被烧焦。

解决方案是限制对Anorm API的访问权限到您代码的有限模块/包/区域

  • Anorm API将是私有的,只能从极少数地方访问,在那里可以轻松执行必要的控制。这部分代码将公开API
  • 代码的每个其他部分都需要通过该API,在" safe"中有效地使用Anorm。方式

答案 1 :(得分:0)

看起来您已经找到了解决此问题的方法 - 您有一个exists()函数可以干净地处理空列表。问题是人们正在编写自己的exists()函数,而这些函数并不是这样做的。

您需要确保您的函数可以作为实用程序函数访问,以便您可以在需要时重用它,而不必重写函数。