【问题标题】:iBatis Discriminator on Insert插入时的 iBatis 鉴别器
【发布时间】:2011-08-15 20:05:27
【问题描述】:

我有一个抽象类Example 和具体的子类来配合它。我使用鉴别器将数据从数据库中提取出来,如下所示:

<resultMap id="ExampleResultMap" class="Example">
    <discriminator column="stateCode" javaType="java.lang.String">
        <subMap value="AL" resultMap="AlabamaStateResultMap"/>
        <subMap value="AR" resultMap="ArkansasStateResultMap"/>
        [...]
    </discriminator>
</resultMap>

<resultMap extends="ExampleResultMap" 
           id="AlabamaStateResultMap"
           class="AlabamaState"/>
<resultMap extends="ExampleResultMap" 
           id="ArkansasStateResultMap"
           class="ArkansasState"/>
[...]

因此我有一个AlabamaState 对象(抽象Example 对象的子类),他没有任何属性。这是人为的,但要点是我没有任何唯一标识对象类型的属性——如果不是这种情况,我没有理由这样做。

注意:这些类不是空的,它们是行为,因此无法将它们重构为不存在。)

如何将其保存回数据库?

理想情况下,ParameterMaps 应该有一个 Discriminator,但似乎没有。

据我所知,有很多不受欢迎的解决方案,其中包括:

  • 放弃并在我的所有返回静态字符串的子类上添加一个“getType()”方法。在这种情况下,AL。 (请注意,我非常努力地避免在我的所有代码中都需要这个,所以这 = OOD-defeat)。
  • 制作一个“DB”对象,它与我的大型复杂对象完全一样,但碰巧还有一个额外的字符串,上面写着“哦,顺便说一句,我的 TYPE 是 AL”。
  • 在插入对象之前,将我想要保留的所有 20 个属性提取到 HashMap 中。
  • 其他一些疯狂的事情,比如使用 toString() 或其他东西来帮助我。

我可能会选择第一个选项,但这似乎很荒谬,不是吗?如果iBatis可以创建它,它不应该可以持久化它吗?我真正需要的是插入的鉴别器。

是我运气不好,还是我忽略了一些明显的东西?

【问题讨论】:

  • 你能发布你的 ExampleResultMap 吗?
  • 我重写了这个问题......希望现在更清楚了。请注意,resultMap 是创建对象 (db->java) 的示例,现在我想将其保存回 db。
  • 用你的例子; CaliforniaState 对象是否有可能声明一个其他州没有的变量?
  • @Gabriel 你找到解决方案了吗?
  • 遗憾的是,我将类型添加到我的对象中。

标签: java ibatis


【解决方案1】:

如果你没有属于你的子类的属性,你应该考虑删除这些子类并为你以前的基类添加一个枚举,因为你的子类服务的唯一目的是区分你的对象的类型(如果我理解你的话正确)。为此使用枚举更容易在客户端代码中扩展和优雅(因为您可以打开枚举而不是使用 instanceof 表达式块)。

如果在您的子类上有特定操作的特殊实现,您也可以将它们移动到枚举中,并将您的基类委托给枚举上的实现。

编辑

这是一个例子:

public interface GreetingStrategy {
    abstract String sayHello();
}

enum UserType implements GreetingStrategy {
    ADMIN {
        @Override
        public String sayHello() {
            return "hello from admin";
        }
    },

    GUEST {
        @Override
        public String sayHello() {
            return "hello from guest";
        }
    };

}

class User {

    private final GreetingStrategy greetingStrategy;

    public User(GreetingStrategy greetingStrategy) {
        this.greetingStrategy = greetingStrategy;
    }

    public String sayHello() {
        return greetingStrategy.sayHello();
    }

}

【讨论】:

  • 不可能真正扩展枚举,所以我假设你建议我在我的枚举的自定义方法中创建一个巨大的 if-else 块?不是粉丝!此外,当您确切知道要处理的选项(例如状态机)时,拥有一个实际的类对代码的可读性非常有益。
  • 我觉得我说得不够清楚。对于“扩展”,我不是指继承。引入这样的枚举不会要求您编写巨大的 if-else 块。 (好吧,如果您的客户端代码中还没有带有 instanceof-tests 的巨大 if-else 块来确定子类型,那么至少不会。)。我的观点是: 1. 如果你的子类没有声明任何字段和方法,你应该考虑用枚举替换它们。如果你有没有字段但有方法的子类,你也可以用枚举替换它们,并在枚举本身上声明方法。
  • 我在原始答案中添加了一个示例。
  • 我同意在某些情况下,使用简单的枚举比使用臃肿的子类设计更好。这个问题专门试图解决枚举不足的情况。就我而言,我的“空”(从数据库的角度来看)类充满了行为。类本身父(has-a)对象的状态,每个都包含六个基于事件的规则。尽管如此,最后,父对象只需要保留状态(您的 State 最终成为哪个子类)。
  • 如果您的子类没有任何可变状态,那么枚举就是您的场景的完美匹配。枚举在设计上是可变的和单例的。如果你只是用你的子类来表示一个状态,我肯定会选择枚举。我想不出子类的劣势,除了你不能 declare 单独对单个枚举常量进行操作(但你可以有一组固定操作的不同实现)。但我不想听起来教条 - 也许我只是在你的特殊场景中遗漏了一些重要的东西。
猜你喜欢
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多