我有一些实体类与其他实体有一对一和/或一对多的关系。
我尝试制作一个反映我案例的非常通用的例子......假设我将以下表存储在数据库中(不允许空值):
operations (ID, workerID, customerID, etc_etc)
workers (ID, email, password, etc_etc)
customers (ID, etc_etc)
mobilePhones (workerID, phoneNumber)
应该很清楚:
因此我有以下实体类:
public class Customer {
private int id;
//other fields, then constructors, getters and setters
}
public class Worker {
private int id;
//other fields
private String[] mobilePhones;
}
正如我在标题中所说,我不能使用ORM ,例如Hibernate,所以我将使用DAO。
{编辑:我应该知道你很想知道为什么我不能使用ORM ......好吧,正如我在这里的评论中写的那样:这是一项任务(软件工程考试项目)。 }
现在,我想我对WorkerDAO
不会有任何问题,可以通过mobilePhones
选择workerID
Operation
所有电话号码轻松管理一对多关系等于实际工人的身份。
对我而言,真正的问题是如何管理Worker
及其关联Customer
和Operation
之间的关系。
如果我想避免浪费内存,我应该像这样设计我的public class Operation { // here I have some doubts
private int id;
private int workerId;
private int customerId;
//other fields
}
实体:
public class Operation { // here I have some doubts
private int id;
private Worker worker;
private Customer customer;
//other fields
}
或者可能是这样的:
Operation
后者似乎更像面向对象,但有一个微不足道的含义:即使OperationDAO
的客户端可能不需要它们,工作者和客户的实例也必须在内存中。
更糟糕的是:如果List<Worker>
将工作人员和客户设置为新的工作人员和客户实例,这将导致内存引用同一工作人员/客户的几个实例(例如,两个操作)由同一个工人执行)。
除了浪费内存之外,这肯定会导致数据不一致(例如,一个实例被修改而不更新其他实例)。
为了避免这种情况,应该引入一些知道当前加载了哪些实例的类(例如使用类似List<Customer>
,{{1}}等的东西)...老实说这似乎让我成为一个矫枉过正的人。
我还以为我可以尝试实现某种 lazy fetching ,例如仅在第一个请求时设置工作器实例,但我仍然需要一些跟踪内存和必须查询内容的类;我甚至不知道这个类是否应该与数据访问逻辑或业务逻辑相关(我猜的是前者但仍不确定)。
无论如何,没有理由实现所有这些,因为我不需要缓存系统(我觉得它看起来很像)。
有什么建议吗?
答案 0 :(得分:1)
您不能使用框架,但您可以使用框架本身使用的模式。所以我建议你基于P of EAA. by Martin Fowler
这些解决方案您可以使用第一个选项(使用workerId和customerId字段进行操作),并为每个实体(操作,工作人员,客户)使用Row Data Gateway。 现在,如果内存是一个问题,而您的模型需要它,请使用Identity Map控制所有正在加载工作和客户的实例,并避免重新加载。
您可以使用第二个选项(在操作中有工作人员和客户实例),并使用Table Data Gateway和Lazy Load仅在需要时加载实例
担心是否加载了多个实例取决于您正在构建的应用程序类型以及实例的范围;例如,如果您是创建基于CRUD的应用程序,您的实例通常会有一个请求范围,因此请使用第二种方法,不要担心内存浪费或数据不一致。
建议:使用界面来定义类型。
答案 1 :(得分:0)
我会使用Spring JDBC或模板方法模式的其他一些实现。每个实体1个DAO类。关于事务问题,您可以通过在JDBC连接上调用setAutoCommit(false)并处理所有查询的结果来自行管理它们。
通过重新发明轮子祝你好运:]
答案 2 :(得分:0)
通常我更喜欢
public class Operation {
private int id;
private Worker worker;
private Customer customer;
//other fields
}
因为这更加面向对象并且更容易获取。但是因为你特别远离ORM(我不知道为什么???)所以它似乎是
public class Operation {
private int id;
private int workerId;
private int customerId;
//other fields
}
是更好的选择,您可以随时加载对象。
ORM将是第一选......:)
答案 3 :(得分:0)
我正在回答自己,哈哈。
关于我在davidmontoyago答案的评论中解释的问题,我认为实现目标的最简单方法可能如下:
我尝试绘制一些代码:
/* The class that will cache istances. */
static final class Cache { // package-private, so that only DAOs can see it.
private static final int CAPACITY = 100; // max 100 istance per entity
/* I will track each instance by its id, that is an Integer */
private static Map<Integer,Worker> workers;
private static Map<Integer,Customer> customers;
private static Map<Integer,Operation> operations;
private Cache() {} // I don't really need to istantiate this class
// SOME OPERATIONS
public static boolean isCached(Worker w);
public static boolean isCached(Customer c);
public static boolean isCached(Operation o);
public static Worker getWorker(int id);
public static Worker getCustomer(int id);
public static Worker getOperation(int id);
public static void addWorker(Worker w);
public static void addCustomer(Customer c);
public static void addOperation(Operation o);
}
class DAOWorkerImpl implements DAOWorker {
public find(int id) {
Worker w = null;
if (Cache.isCached(id))
w = Cache.getWorker(id);
else {
//retrieve worker
Cache.addWorker(w);
}
return w;
}
}
你怎么看?这似乎很简单,它应该发挥作用。
在写这段代码的时候,我想也许更好的做法是避免编写Cache
类并让管理所有它们各自的DAO(例如DAOWorker
管理Worker
内存中的实例。 1}}等等。)
唯一不能说服我的是,这可能会打破Single Responsability Principle ......你怎么看待它?