java - 基于数据库父子表建模类的正确方法

标签 java mysql oop model-view-controller model

我认为最好向比我更有经验的 SO 社区提出这个问题。因为我还是个学生。

我知道建模类并将它们与数据库表的关系相匹配对代码的可读性有非常显着的影响,特别是当程序或系统随着添加越来越多的代码而不断增长时。

假设我有实体客户地址订单

所以我认为它具有以下代表实体的模型类。

//with getters and setters 
Customer 
Address
Order

数据访问对象 接口(interface)可能具有以下内容。

CustomerDao
List<Customer> getAllCustomers();
Customer getCustomerById(Customer customer);
boolean addCustomer(Customer customer);

AddressDao
List<Address> getAllAddress();
Address getAddressByCustomer(Customer customer);
boolean addAddress(Address address);

OrderDao
List<Order> getOrdersByCustomer(Customer customer);
boolean addOrder(Order order);

数据访问对象实现

//where I will define the Dao methods.
CustomerDaoImpl implements CustomerDao
AddressDaoImpl implements AddressDao
OrderDaoImpl implements OrderDao

我还没有尝试过使用 MVC 模式在 Java 中进行编程,但我使用 DAO 模式。因此,在上面的示例中,DAO/DAOImpl 的工作方式就像一个 Controller ,负责在数据库中存储和检索数据。

从模式角度来看,除了客户、地址和订单之外,它可能还有其他表。 表将是customeraddressorder,它也可能具有连接表,例如customer_address customer_order

我应该在 Java 端编程中创建 CustomerAddressCustomerOrder 类吗?

另外说我想使用 getCustomerById() 方法,是否最好使用 Customer 作为参数,如 getCustomerById(customer)而不是 getCustomerById(int customerId);

有人告诉我,model 类代表数据库中一个表中的一行。

我知道大多数使用 MVC 框架的人可能有更简单的方法来生成代码并使用不同的 IDE 关联类的模型。但是,如果我尝试使用匹配的数据库表对类进行建模,就像从头开始使用 dao 一样,该怎么办?

如果有任何建议,我将不胜感激。我正在开发一个项目,其中有一些 ID getters,我使用 model 作为参数,如 getOrderByCustomerId(Customer customer) 中那样,而不是getOrderByCustomerId(int customerId);

如果您可以对我的建模方式添加最佳实践和更正,那就太好了。

谢谢。

最佳答案

我可能不会直接回答您如何建模,但想象一下当您根本没有数据库时的情况。你会怎么办?

当您以这种方式思考时,它可以帮助您在域和持久模块之间设置边界。如果没有任何持久性,您可以使用简单的 HashMap 作为内存存储。

然后这样的 HashMap 将提供客户 ID 到 Customer 的映射。拥有客户可以为您提供她的地址和她的订单。关于 getAddressByCustomer 究竟如何实现的所有细节都被隐藏了,这将是封装的一个很好的例子。类似的东西

public static class Customers {
    private final Map<Integer, Customer> cache;

    public Customers(Map<Integer, Customer> cache) {
        this.cache = cache;
    }

    public Customer findById(Integer id) {
        return cache.get(id);
    }
}

public static class Customer {
    private final Address address;
    private final List<Order> orders;

    public Customer(Address address, List<Order> orders) {
        this.orders = orders;
        this.address = address;
    }

    public List<Orders> lastWeekOrders() {
        // I bet real people know what they bought last week...
        return ...;
    }
}

public static class Address {
}

public static class Order {
}

因此,Customers 对象需要一个 Cache 来履行其职责以及它到底如何做到这一点 - 他自己的事。现在,假设您正在使用数据库,那么另一个 Customers 对象将获得对某种 DataSource 的引用,以便它可以对其运行 SQL。根据需要,可以永久缓存某些内容或一段时间,但同样 - 它的所有内部细节,没有人关心它内部如何工作。

当您遇到这样的情况时,您应该会更清楚地意识到,如何保留所有这些数据并不是很重要。它可以是单个表,也可以是具有一对一或多对多关系的几个表。重要的是,此示例中只有一个 Customers 对象了解如何检索所有这些信息。我并不是说我不关心性能,但那是后来的事。对于已知的工作负载,我们可以创建特定的索引。如果速度很慢,我们可以以不同的方式重新排列数据以获得更快的速度,甚至可能对某些东西进行非规范化以获得更快的速度,但所有这些都是在测量之后进行的,无论如何,在这种设计中,所有这些细节都将被封装在其中单个 Customers 实体。

这样你最终就会得到一些真实的对象,比如客户地址,它们会知道他们自己的名字、年龄、他们居住和工作的建筑物、他们最后的订单,等等,而不是一些愚蠢的 DTO,它们只能获取和设置一些字符和数字,而不知道它们是什么。没有办法以任何其他方式使用 DTO,直接将它们映射到一堆表。

Customers 对象可能看起来像 DAO,但我认为它不是 - 取决于 POV。 Hibernate 也可以使用它的所有功能、惰性、缓存等,但在 Customers 内部,因此它位于边界的右侧。

关于java - 基于数据库父子表建模类的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42734430/

相关文章:

c# - 为什么声明没有给出CS0201编译器错误?

java - 使用 BigInteger 重写 public int hashCode()

java - Android 相机剩余空间

php - 如何获取表1中的所有记录和表2中的元数据?

php - 从 2 个来源提取信息并计数

matlab - 是否可以使用枚举作为 MATLAB 矢量或 map 的下标?

.net - 衡量面向对象的指标

java - 加快提取 Zip 文件

java - Hibernate和ID生成器: at which point is the id generated?

mysql - 使用 MySQL 如何更好地选择所有人及其工作,排除从事特定工作的人?