【发布时间】:2015-09-24 03:31:50
【问题描述】:
在使用 SpringJDBC 模板时,我一直在反复研究用 Java 设计和实现域层的最佳方法。我想设计一些可重用且健壮的东西,同时避免 n+1 查询问题和性能问题。我提出了几个案例,但不确定哪一个最适合与 JDBC 一起使用。我以前使用过休眠。假设 SpringJDBC 将是与数据库交互的技术,那么在 Java 中进行域设计的最佳方法是什么。
例如,假设我有一个地址,它有一个州,它有一个国家。
案例 1:域对象与数据库完全匹配
public class Address {
private long id;
private String streetLine1;
private String streetLine2;
private String city
private long stateId;
private String zipCode;
...
}
public class State {
private long id;
private String name;
private String code;
private long countryId;
}
public class Country {
private long id;
private String name;
private String code;
}
在这种情况下,域对象是数据库表的精确表示,因此行映射很简单,并且可以将对象持久化到数据库中。
我可以看到的主要缺点是,假设在用户界面上我需要列出应用程序中的所有地址,以及想要的街道 1、街道 2、城市、州(全名)、邮政编码和国家。如果返回了 100 个地址,那么我需要为每行发出两个额外的查询以获取 State 对象和 Country 对象,总共执行了 201 个查询,哎呀!
案例 2:
遵循与案例 1 相同的设计,但是当您遇到 UI 需要来自多个域对象的组件的情况时,通过将 RowMapper 映射到 DTO 对象而不是域来返回自定义 DTO 对象,从而可以执行一个查询。我在这里看到的缺点是您最终可能会得到大量特殊情况的 DTO / Model 对象。
public class AddressDTO {
private long id;
private String streetLine1;
private String streetLine2;
private String city;
private String state;
private String country;
}
案例 3:
映射类似于在休眠中域对象相互引用的方式。然而,现在 RowMappers 变得更加复杂,它们可能会不必要地获取数据。在这一点上,预计对象将始终被填充,因为没有像 JPA/Hibernate 那样的延迟加载。为了持久化和 Address,Address 对象需要一个有效的 State 对象关联。这似乎是最不实用的解决方案,但我可能有些东西我不理解。
public class Address {
private long id;
private String streetLine1;
private String streetLine2;
private String city
private State state;
private String zipCode;
...
}
public class State {
private long id;
private String name;
private String code;
private County country;
}
public class Country {
private long id;
private String name;
private String code;
private Set<State> states;
}
【问题讨论】: