简体   繁体   English

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

[英]How to prevent unintended default values from MyBatis queries?

I have the following Java class:我有以下 Java class:

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

The class represents a database table called example . class 表示一个名为example的数据库表。 I can use the following SQL query to fetch Example instances from the table with MyBatis:我可以使用以下 SQL 查询通过 MyBatis 从表中获取Example实例:

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

Let's say that I will add a new field to the table and the class: boolean third .假设我将在表中添加一个新字段和 class: boolean third However, if I don't remember to add the field to the select queries, it will have the default value of false .但是,如果我不记得将该字段添加到 select 查询中,它将具有默认值false This could lead to unexpected results when checking the value.检查值时,这可能会导致意外结果。 Same thing would happen also if a new query was created in the future but without all the fields.如果将来创建了一个新查询但没有所有字段,也会发生同样的事情。

One solution is to use Boolean instead of boolean .一种解决方案是使用Boolean而不是boolean Then it would throw a NullPointerException if trying to evaluate third without the value present.然后,如果尝试在不存在值的情况下评估third ,它将抛出NullPointerException Even this would still be prone to a developer mistake, ie a redundant null check.即使这样仍然容易出现开发人员错误,即冗余 null 检查。 For example:例如:

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

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

Is there some solution that would enforce fetching all property values?是否有一些解决方案可以强制获取所有属性值?

You are hitting the limitation of Java here so the is no elegant solution to this without the help of a 3rd party library (which is still great and I highly recommend).您在这里遇到了 Java 的限制,因此如果没有 3rd 方库的帮助(这仍然很棒,我强烈推荐),没有优雅的解决方案。

Use constructor injection and not property injection in result maps and also use lombok to automatically generate constructors for you (and/or lombok's @NonNull checks if you use Boolean ).在结果映射中使用构造函数注入而不是属性注入,并且还使用lombok为您自动生成构造函数(和/或 lombok 的@NonNull检查您是否使用Boolean )。

So if you have class:因此,如果您有 class:

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

When you add a new field to it the constructor for it will be automatically changed to include that new field.当您向其添加新字段时,它的构造函数将自动更改为包含该新字段。 Given that you use constructor injection that will force you to add new column to all queries using the class.鉴于您使用构造函数注入,这将迫使您使用 class 向所有查询添加新列。

The mapping should be like this:映射应该是这样的:

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

After the change the mybatis will complain during query execution that constructor with two parameters is not found or that fields are not present in the result and this will force you to change the query and/or mapping.更改后,mybatis 将在查询执行期间抱怨找不到具有两个参数的构造函数或结果中不存在字段,这将迫使您更改查询和/或映射。

You can also use autoMapping=true in resultMap so that you don't need to specify fields explicitly and you will need to update only the queries.您还可以在resultMap中使用autoMapping=true ,这样您就不需要显式指定字段并且只需要更新查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM