java - DAO设计和数据结构

标签 java database dao

在我的 java 应用程序中,我想为数据库操作实现抽象层。我不想将我的应用程序绑定(bind)到任何类型的数据库(实现可以是任意的:SQL、XML、基于文档、一堆丑陋的文本文件等)

实体之间有很多关系,大多数时候是一对多的关系。

更新和免责声明:虽然示例很简单,但它们只是整个更复杂模型的一部分,它们很可能不适合 ORM/SQL 模型(两者都是因为数据量很大:~由于数据的不同性质,当归一化为关系时有数十亿条记录)。我在这里问的是实现简单的关系,但这并不意味着它们构成了应用程序的唯一问题。

一个简化的例子如下:

public class Vehicle {
    String mark;
    String model;
    String registrationId;
}

public class Depot {
    String name;
    String address;
}

这些实体中的每一个都有自己的 DAO 接口(interface):

public interface VehicleDAO {
    List<Vehicle> getVehicles();
    Vehicle getVehicleByRegistrationId(String registrationId);
}

public interface DepotDAO {
    List<Depot> getDepots();
    Depot getDepotByName(String name);
}

这些 DAO 也被简化了,只是为了展示一些为特定实体隔离的方法(通过其注册 ID 获取车辆我不需要知道任何关于其他实体的信息)。

现在有趣的部分来了。 Depot 和 Vehicle 之间的关系是一对多的。所以我必须在我的实体类和 DAO 方法中实现这种关系。

现在我有两种方法:

  • 地点List<Vehicle>里面的属性(property)Depot类并在我获取 Depot 时填充它实例(具有可能的延迟获取改进)。这样 DAO 接口(interface)就不会改变。
  • Depot 引入特殊标识符和 Vehicle ,以便实体类获得额外的整数属性 int id;我们向 DAO 添加一个方法 List<Vehicle> getVehiclesForDepot(int depotId) .可以通过为标识符而不是普通整数引入特殊类来增强这种方法。

也许还有其他方法?为实体之间的关系建模和设计 DAO 接口(interface)以保持数据库抽象易于使用且不绑定(bind)到任何类型的数据库的最佳方法是什么?我问的不一定是完整准确的解决方案,而是解决上述问题时的一些原则。

最佳答案

在您的示例中,您使用了本地化为 DAO 类型的方法,最好定义一组一致的 DAO 方法来涵盖这些功能,即

// load object of DAO type T
<T> load(id)
// load objects of DAO type T
List<T> load(List<id>)
// load all objects of DAO type T
List<T> find()
// load multiple objects of DAO type T
List<T> find(relation)

等等,如果你使用一致的id输入(例如 long)你可以定义一个 interface涵盖您的基本方法。

要加载关系,您有几个选择,这最好取决于您对对象及其关系的使用:

  • 制作List<T>数据持有者的一个属性并将其填充为 load() 的一部分

这适用于少量关系,当相关实体与其他实体没有关系时。如果他们这样做,您将不得不部分加载它们以防止预先加载太多(您提到的延迟加载是一种策略。)

  • 制作List<T_id>数据持有者的一个属性并将其填充为 load() 的一部分

这适用于适量的关系,与 load(List<id>) 一起使用访问相关实体的方法。

对于大量数据,正如您提到的是您要解决的大部分问题,您可以进一步分离关系并使用 DAO 方法,例如:

// retrieve related entity id's for this DAO T
List<id> loadIds(T)

加载(外国)集id用于与作为参数传递的数据持有者对象有关系的实体。然后,您的管理器/业务/服务层使用该 ID 列表来加载下一组实体,可能通过将偏移量传递到 ID 列表和要加载的实体数量来分块。

或者,您可以通过添加 DAO 方法来解耦有关关系的知识,以填充另一种 DAO 类型的数据持有者对象中的外部关系:

// fill entity relations for T2 to this DAO tyoe T
void fill(T2)

T::fill()方法将在 T2 上使用 setter/getter 获取确定要加载的相关实体(或其 id 的)所需的数据,以及一个或多个 setter 将该信息存储在 T2 中数据持有者对象。

大多数这些 DAO 的加载方法会将关系数据集保留为 null留待以后加载。这当然意味着他们的数据持有者对象 getter 必须能够处理 null值(value)作为契约(Contract)的一部分。

关于java - DAO设计和数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8601327/

相关文章:

sql - 如何从postgres中的查询中提取小时数

database - 有效的 JMS 处理

java - DAO 方法应该调用同一类中的另一个方法还是应该由服务层执行?

java - 高级Java泛型问题: why do we need to specify redundant information

java - 是否可以通过环境变量设置 spring.datasource.driver-class-name?

java - 无法应用Jlabel;原因: actual and formal argument list differ in length

java - Jsoup.connect() 的 get 方法阻塞 UI

java - 尽管为 api 11 及更高版本设置了 list ,但 Android api 级别 14 上的 GridView 崩溃

android - SQLiteDatabase.openDatabase(...) 与 getWritableDatabase

java - 使用 Spring Data 将数据传递到 MongoDB 的方法