【问题标题】:Can I configure myBatis to create an instance of a class using the Builder Pattern?我可以配置 myBatis 以使用 Builder 模式创建类的实例吗?
【发布时间】:2013-03-28 16:08:22
【问题描述】:

我有一个 (Java) 类,其中包含许多实例字段(其中许多是可选的)。我希望所有字段(因此类)都是不可变的。所以,我想使用 Builder Pattern 来构造类的实例。

我可以配置 myBatis 以使用 Builder 模式创建一个类的实例吗?我知道我可以让 myBatis 返回一个地图并使用该地图在我的代码中构建实例。但是,我正在寻找一种配置此映射(或使用某种约定)的方法,类似于如何通过使用 Java Bean 和构造函数来创建实例。

编辑(包括示例)

这是一个例子:

package com.example.model;

// domain model class with builder
public final class CarFacts {

    private final double price;
    private final double numDoors;
    private final String make;
    private final String model;
    private final String previousOwner;
    private final String description;

    public static class Builder {
        // required params
        private final double price;
        private final String make;
        private final String model;

        // optional params
        private final String previousOwner;
        private final String description;
        private final double numDoors;

        public Builder(double price, String make, String model) {
            this.price = price;
            this.make = make;
            this.model = model;
        }

        public Builder previousOwner(String previousOwner) {
            this.previousOwner = previousOwner;
            return this;
        }
        // other methods for optional param

        public CarFacts build() {
            return new CarFacts(this);
        }
    }

    private CarFacts(Builder builder) {
        this.price = builder.price;
        //etc.
    }
}

然后,我有一个映射器:

<!-- this doesn't work but I think h3adache suggest that I could have the resultType
be com.example.model.CarFacts.Builder and use the Builder constructor. But I'm not sure how
I would call the methods (such previousOwner(String)) to populate optional params -->

<mapper namespace="com.example.persistence.CarFactsMapper">
  <select id="selectCarFacts" resultType="com.example.model.CarFacts">
    select *
    from CarFacts
  </select>
    
</mapper>

最后,我有了映射器界面:

package com.example.persistence.CarFactsMapper;

public interface CarFactsMapper {
    List<CarFacts> selectCarFacts();
}

我还希望能够通过 myBatis 使用静态工厂方法创建实例。例如:

public final class Person {

    private final String lastName;
    private final String firstName;

    private Person(String lastName, String firstName) {
        this.lastName = lastName;
        this.firstName = firstName;
    }

    public Person newInstance(String lastName, String firstName) {
        return new Person(lastName, firstName);
    }
}

具体来说,如何让 myBatis 调用 newInstance(String, String)?

【问题讨论】:

标签: java mybatis builder-pattern static-factory


【解决方案1】:

您不需要使用构建器或静态工厂方法。是的,如果您试图保持不变性,这些模式肯定帮助,因为可能会发生突变,我们是否应该说“实例之间”,例如因为构建器在调用 build()(创建一个新的不可变实例)之前发生了变异。

但是,不变性独立于给定实例的构造方式。我们无法为可变类编写构建器和静态工厂方法。在构建时,所有对象还没有发生变异,所以真正重要的是接下来会发生什么(在建造者和工厂离开之后)。

您需要做的就是关注类本身,并认为这个类是不可变的。常规的 myBatis 映射应该没问题 - 节省自己编写构建器的时间。

所以 - 你的类是不可变的,是的,因为你的所有字段都是最终的,要么是原始类型,要么是字符串(在 Java 中是不可变的!)。如果您有其他非原始字段,那么您希望它们是最终的(从技术上讲,您不需要编写 final,但建议您,只要该字段实际上从未被重新分配)并且您希望他们的类一直遵循这些规则的递归。

我希望这会有所帮助,我想说明的一点是,构建器模式和工厂方法非常适合管理构造,但它们不能免费为您提供不变性,您总是需要编写构造器。

【讨论】:

  • 这没有回答问题。
猜你喜欢
  • 2014-10-06
  • 1970-01-01
  • 2022-11-09
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多