如何防止 MyBatis 查询中出现意外的默认值?

How to prevent unintended default values from MyBatis queries?

我有以下 Java class:

// Java
class Example {
  boolean first;
  boolean second;
}

class 表示名为 example 的数据库 table。我可以使用以下 SQL 查询从 table 和 MyBatis 中获取 Example 个实例:

// SQL
select
  first as example_first,
  second as example_second
from example 

假设我将向 table 和 class 添加一个新字段:boolean third。但是,如果我不记得将字段添加到 select 查询,它将具有默认值 false。这可能会在检查值时导致意外结果。如果将来创建新查询但没有所有字段,也会发生同样的事情。

一种解决方案是使用 Boolean 而不是 boolean。然后,如果尝试在没有值存在的情况下评估 third,它将抛出 NullPointerException。即使这样仍然容易出现开发人员错误,即冗余的空检查。例如:

// Java
final Example e = database.fetchExampleWithoutThird(); // third field missing from query

if (e.third != null && e.third.booleanValue()) {
  // never executes
}

是否有一些解决方案可以强制获取所有 属性 值?

您在这里遇到了 Java 的限制,因此如果没有第 3 方库的帮助(这仍然很棒,我强烈推荐),就没有优雅的解决方案。

在结果映射中使用构造函数注入而不是 属性 注入,并且还使用 lombok 自动为您生成构造函数(and/or lombok 的 @NonNull 检查您是否使用 Boolean).

所以如果你有 class:

@AllArgsConstructor  // this generates constructor with parameters for every field
class Example {
  boolean first;
  boolean second;
}

当您向它添加新字段时,它的构造函数将自动更改为包含该新字段。鉴于您使用构造函数注入,这将迫使您使用 class.

向所有查询添加新列

映射应该是这样的:

<resultMap id="exampleResultMap" type="Example">
  <constructor>
    <arg column="first" javaType="boolean"/>
    <arg column="second" javaType="boolean"/>
  </constructor>
</resultMap>

更改后,mybatis 会在查询执行期间抱怨未找到具有两个参数的构造函数或结果中不存在字段,这将迫使您更改查询 and/or 映射。

您还可以在 resultMap 中使用 autoMapping=true,这样您就不需要明确指定字段,只需更新查询即可。