实现没有ORM的实体类之间的关系

时间:2012-08-21 15:48:34

标签: java database design-patterns dao


我有一些实体类与其他实体有一对一和/或一对多的关系。

我尝试制作一个反映我案例的非常通用的例子......假设我将以下表存储在数据库中(不允许空值):

   operations (ID, workerID, customerID, etc_etc)
      workers (ID, email, password, etc_etc)
    customers (ID, etc_etc)
 mobilePhones (workerID, phoneNumber)

应该很清楚:

  • 1 操作只有 1 工作人员和 1 客户。
  • 1 客户至少 1 手机号码。

因此我有以下实体类:

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及其关联CustomerOperation之间的关系。 如果我想避免浪费内存,我应该像这样设计我的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 ,例如仅在第一个请求时设置工作器实例,但我仍然需要一些跟踪内存和必须查询内容的类;我甚至不知道这个类是否应该与数据访问逻辑业务逻辑相关(我猜的是前者但仍不确定)。

无论如何,没有理由实现所有这些,因为我不需要缓存系统(我觉得它看起来很像)。

有什么建议吗?

4 个答案:

答案 0 :(得分:1)

您不能使用框架,但您可以使用框架本身使用的模式。所以我建议你基于P of EAA. by Martin Fowler

这些解决方案
  1. 您可以使用第一个选项(使用workerId和customerId字段进行操作),并为每个实体(操作,工作人员,客户)使用Row Data Gateway。 现在,如果内存是一个问题,而您的模型需要它,请使用Identity Map控制所有正在加载工作和客户的实例,并避免重新加载。

  2. 您可以使用第二个选项(在操作中有工作人员和客户实例),并使用Table Data GatewayLazy Load仅在需要时加载实例

  3. 担心是否加载了多个实例取决于您正在构建的应用程序类型以及实例的范围;例如,如果您是创建基于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答案的评论中解释的问题,我认为实现目标的最简单方法可能如下:

  • 有一个类,用于跟踪从DB加载并在内存中的实例。这可能是一种实用类,我的意思是私有构造函数和所有静态方法。
  • 确保返回实体类实例的所有DAO检查请求的实例是否在缓存中;如果是,则返回该实例,否则从数据库加载它并将其添加到缓存中。

我尝试绘制一些代码:

/* 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 ......你怎么看待它?