Java 数据库关系建模
我认为描述这个问题最好的方法是用一个例子。我将通过删除不必要的实现细节来尽可能地简化它 假设有一家书店。商店使用后端数据库存储所有数据,并使用Java前端将数据呈现给商店经理,以跟踪所有书籍、客户和订单 数据库包含以下关系:Java 数据库关系建模,java,design-patterns,data-modeling,Java,Design Patterns,Data Modeling,我认为描述这个问题最好的方法是用一个例子。我将通过删除不必要的实现细节来尽可能地简化它 假设有一家书店。商店使用后端数据库存储所有数据,并使用Java前端将数据呈现给商店经理,以跟踪所有书籍、客户和订单 数据库包含以下关系: 书(id、标题、作者) 客户(身份证、姓名、电话、地址) 订单(id、日期、客户id、bookId) 另一方面,Java接口使用驱动程序连接到数据库并检索数据。该应用程序由以下类别组成: 书籍 BooksDataLoader BooksTableModel BooksVie
BooksDataLoader
BooksTableModel
BooksView
客户
CustomerDataLoader
CustomerTableModel
CustomerView
订单
OrdersDataLoader
OrdersTalbeModel
订单视图
这些类使用各自的设计准则,您可以使用以下源代码作为参考:
public class Book {
private String id;
private String title;
private String author;
/*
* Builder pattern is used so constructor should be hidden. Book objects
* are built in the BooksDataLoader SwingWorker thread.
*/
private Book() {}
}
public class BooksDataLoader extends SwingWorker<List<Book>, Book> {
private final BooksTableModel booksModel;
private final List<Book> books = new ArrayList<Book>();
}
public class BooksTableModel extend AbstractTableModel {
private final String columnNames = { "Book ID", "Book Title", "Book Author" };
private final List<Book> books = new ArrayList<Book>();
}
public class BooksView extends JPanel {
private final JTable booksTable;
private final BooksTableModel booksModel;
}
公共课堂教材{
私有字符串id;
私有字符串标题;
私有字符串作者;
/*
*使用了生成器模式,因此应该隐藏构造函数
*内置在BookDataLoader SwingWorker线程中。
*/
私人书籍(){}
}
公共类BooksDataLoader扩展SwingWorker{
私人最终书桌模型书桌模型;
私有最终列表书籍=新ArrayList();
}
公共类BooksTableModel扩展AbstractTableModel{
私有最终字符串columnNames={“图书ID”、“图书标题”、“图书作者”};
私有最终列表书籍=新ArrayList();
}
公共类BooksView扩展了JPanel{
私人最终JTable书桌;
私人最终书桌模型书桌模型;
}
我正在使用实现Book、Customer和Order类。这些类的实例是使用SwingWorker线程内的数据库检索的数据构建的,并使用AbstractTableModel发布到视图中。因此,实际上该应用程序由以下视图(JPanel)组成:BookView、CustomerView和OrdersView,每个视图都包含一个JTable,其中的列如下所示:
BooksView.booksTable:图书ID |书名|图书作者CustomerView.CustomerTable:客户ID |客户名称
OrdersView.ordersTable:订单ID |日期|客户名称|书名|书籍作者
当我们试图将表示数据库中外键的实例变量解析为它链接的数据时,就会出现问题。例如,OrdersTableModel具有数据库中所有订单对象的列表结构,但是OrdersView表的第3、4和5列不能直接从订单对象访问,因为它只包含书籍和客户的ID,而不包含实际数据。我尝试的一个解决方案是在Book、Customer和Order类中创建一个静态HashMap,以便跟踪所有检索到的对象,但这会导致数据重复,因为我们在每个视图的表模型中已经有了检索到的对象的列表结构 我正在寻找一个高效、可扩展(面向对象)的设计解决方案/建议
提前感谢。在关系数据库表上映射OO设计时,这是一个典型的问题 让我们以您的OrdersTableModel为例: 订单编号|日期|客户名称|书名|书籍作者 最后三列是数据库外键ID,而不是要显示的值 要正确管理此问题,您有两种可能的解决方案: 第一: 像这样设计订单类
public class Order{
private String id;
private Date date;
private Customer customer;
private Book book;
private Author author;
get and set methods
}
请注意,客户类型为customer,book类型为book
现在假设您查询数据库以检索订单列表。
从返回的行中,必须按顺序构建对象列表。当然,db会返回客户、书籍和作者的外键ID,因此:
listOrders[i].getCustomer().getName(). // listOrders[i] is an Order object. getCusotmer returns a customer object. getName is a Customer's method that return the String name.
书和作者也一样
第二种方法
设计订单类如下所示:
public class Order{
private String id;
private Date date;
private int customer;
private int book;
private int author;
get and set methods
}
注意,现在customer等是INT字段。保持从db检索的int引用键
再次查询表订单
为每行生成一个Order对象。用数据库的id简单地填写customer等值
现在,您需要显示订单列表
在列表上迭代。
显示客户用途时
listOrders[i].getCustomer().getName().
注:由于customer字段是一个int引用键,因此geCustomer应该