基于表设计的类建模

发布于 2024-07-16 22:02:39 字数 509 浏览 4 评论 0原文

这是人们通常设计课程的方式吗? 一类 = 1 个表。 包含另一个表的外键的表怎么样?

假设我有以下内容:

PersonTable
---------------
person_id
name

PersonMapTable
---------------
map_id
type_id (fk)
person_id

PersonTypeTable
-------------------
type_id
description
parent_type_id

AddressTable
-------------------
address_id
address1
address2
city
state
zip

AddressMapTable
-----------
address_map_id
address_id
person_id

好的做法包括为每个表创建一个类吗? 如果是这样,在没有 orm 的情况下将此类类加载/保存回数据库的最佳实践是什么? 一个简单的代码示例会非常有帮助

Is this how one would normally design classes?
One class = 1 Table.
How about tables that contain a foreign key to another table?

Suppose I have the following:

PersonTable
---------------
person_id
name

PersonMapTable
---------------
map_id
type_id (fk)
person_id

PersonTypeTable
-------------------
type_id
description
parent_type_id

AddressTable
-------------------
address_id
address1
address2
city
state
zip

AddressMapTable
-----------
address_map_id
address_id
person_id

Would good practice consist of creating a class for each table?
If so, what are the best practices for loading/saving such classes back to the database without an orm? A simple code example would be really helpful

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

美人骨 2024-07-23 22:02:39

我建议阅读 Martin Fowler 的 企业应用程序架构模式,其中有几种映射模式类和表。

I'd recommend reading Martin Fowler's Patterns of Enterprise Application Architecture, which has several patterns of mapping between classes and tables.

梦年海沫深 2024-07-23 22:02:39

我认为每张桌子一个对象不一定是一个好的设计。 很难给出一个放之四海而皆准的规则,但对象可以更丰富、更细粒度。 数据库可以因不适用于对象的原因而被非规范化。 在这种情况下,您将拥有比表更多的对象。

您的案例将包括 1:1 和 1:m 关系:

public class Person
{
    // 1:m
    private List<your.namespace.Map> maps; 
}

public class Map
{
    // 1:1
    private your.namespace.Type;
}

I don't think that one object per table is necessarily a good design. It's hard to give a one size fits all rule, but objects can be richer and more fine grained. A database can be denormalized for reasons that don't apply to objects. In that case, you'd have more objects than tables.

Your case would include 1:1 and 1:m relationships:

public class Person
{
    // 1:m
    private List<your.namespace.Map> maps; 
}

public class Map
{
    // 1:1
    private your.namespace.Type;
}
天暗了我发光 2024-07-23 22:02:39

在大多数情况下,我倾向于将表映射到实体,但这不是一个硬性规则。 有时,在某些情况下,所讨论的特定实体的存储库最好处理围绕特定实体的一般问题,这意味着它将交叉处理其他表,而不需要这些表特别需要作为实体存在。

从不做的事情(除了在非常具体的计划情况下,总是需要使用实体检索依赖数据)是将一个实体或实体集合设置为另一个实体的属性。 相反,该实体要么可以通过其 ID 发现,该 ID 要么是父实体的属性,要么可以通过与父实体相关的关联存储库发现。

如果我需要将另一个实体的子实体或实体捆绑在一起,我将使用“info”帮助程序类将所有所需的数据组合在一起。 例如,如果我有一个实体类 Widget 并且它有一个子 Part 对象的集合,那么我将创建一个 WidgetInfo 类,它将包含 Widget 实例作为属性,并包含 Part 对象集合作为另一个属性。

这样,所有实体类都尽可能保持轻量级,并且永远不会假设需要加载依赖数据。 它还可以保持存储库模型干净,而不会迫使您进入混乱的 ORM 领域,如果您在实体类上创建子对象集合,通常会出现这种情况。 如果您在没有 ORM 的情况下执行此操作,那么您最终会遇到何时加载子项以及何时假设子项已加载或尚未加载的混乱问题。

For the most part I tend to map tables to entities, but it's not a hard rule. Sometimes there are instances where the repository for a specific entity in question is better off dealing with the general concerns surrounding a specific entity, which means it will cross into dealing with other tables as a result, without those tables specifically needing to exist as entities.

What I never do (except in very specific planned cases where the dependent data ALWAYS needs to be retrieved with the entity), is set an entity or collection of entities as a property of another entity. Instead, that entity will either be discoverable via its ID, which will either be a property of the parent entity or discoverable via the associated repository in relation to the parent entity.

In cases where I need the child entity or entities of another entity to be bundled together, I'll make use of an "info" helper class to pull together all the required data. For example, if I have an entity class Widget and it has a collection of child Part objects, then I would create a WidgetInfo class which would contain the Widget instance as a property and a collection of Part objects as the other property.

This way all entity classes remain as lightweight as they can and never make the assumption that dependent data will need to be loaded. Also it keeps the repository model clean without forcing you into messy ORM territory which is generally the case if you create child object collections on an entity class. If you do that without ORM, then you end up with the messy problem of when to load the children or not, and when to assume that the children have or have not been loaded.

眼趣 2024-07-23 22:02:39

我不会说我总是每张桌子都有班级,特别是当你有多对多关系时。 根据您上面的表格,我将有 2 个课程...我不确定为什么您同时拥有 id 和 person_type_id,对我来说它们是相同的东西,但这里是课程。

Person
{
   public int Id { get; set; }

   public string Name { get; set; }

   public List<PersonType> { get; set; }
}

PersonType
{
   // I would discourage from using Type as property name as it is a keyword...
   public string [Type] { get; set; }
}

I wouldn't say that I always have class per table, especially when you have many to many relationships. Based on your table above I would have 2 classes... I am not sure why you have both and id and a person_type_id, to me they would be the same thing but here are the classes.

Person
{
   public int Id { get; set; }

   public string Name { get; set; }

   public List<PersonType> { get; set; }
}

PersonType
{
   // I would discourage from using Type as property name as it is a keyword...
   public string [Type] { get; set; }
}
森林散布 2024-07-23 22:02:39

除非您的用户是数据输入员,否则通常认为从用例/用户故事中设计类会更好。 即使数据库已经存在。

原因? 用户很容易最终认为他们的工作是使用软件,而不是期望软件帮助他们完成工作。

显然它们需要在某个点相交。 我同意福勒的书是一个很好的起点。 但我认为他会强化这一观点。

如果您想要一个可以帮助您正确获取类和数据库的建模视角,请考虑对象角色建模。

Unless your users are data entry clerks, it's generally considered better to design classes from Use Cases/User Stories. Even if the database already exists.

Reason? It's too easy for users to end up assuming their job is to exercise the software, rather than expecting the software to help them do their jobs.

Clearly they need to intersect at some point. I concur that Fowler's book is a great place to start. But I think he'll reinforce this point of view.

If you want a modeling perspective that helps you get both the classes and the database right, consider Object Role Modeling.

烂柯人 2024-07-23 22:02:39

如果您计划使用对象关系映射 (ORM),这可能会影响您的表设计。 例如,Hibernate 不喜欢同一棵树中的混合继承映射策略。

由于您明确表示您不会使用 ORM,因此您可以遵循传统的数据库设计原则。 这通常意味着从每个类一个表开始,规范化为第三范式(在此处阅读有关数据库规范化的信息),然后反规范化以满足性能约束(在此处阅读有关反规范化的信息)。

关于如何在不使用 ORM 的情况下加载和保存对象的问题,常见的策略是使用数据访问对象 (DAO)。 这是一个简单的例子:

public interface ICustomerDao
{
  public void insert(Customer customer) throws CustomerDaoException;
  public void update(long id, Customer customer) throws CustomerDaoException;
  public void delete(long id) throws CustomerDaoException;
  public Customer[] findAll() throws CustomerDaoException;
  public Customer findByPrimaryKey(long id) throws CustomerDaoException;
  public Customer[] findByCompany(int companyId) throws CustomerDaoException;
}

您没有指定您使用的语言,但无论如何您可能会发现 这个使用 Java 泛型的示例对于 DAO 很有用。

If you plan on using Object-Relational Mapping (ORM), this may affect your table design. Hibernate, for instance, does not like mixed inheritance mapping strategies within the same tree.

Since you specifically indicated that you will not be using ORM, you can follow traditional database design principals. This typically means starting with one table per class, normalizing to third-normal form (read about database normalization here), then denormalizing to meet performance constraints (read about denormalization here).

Regarding your question about how to load and save the objects without the use of ORM, a common strategy is to use Data Access Objects (DAOs). Here is a simple example:

public interface ICustomerDao
{
  public void insert(Customer customer) throws CustomerDaoException;
  public void update(long id, Customer customer) throws CustomerDaoException;
  public void delete(long id) throws CustomerDaoException;
  public Customer[] findAll() throws CustomerDaoException;
  public Customer findByPrimaryKey(long id) throws CustomerDaoException;
  public Customer[] findByCompany(int companyId) throws CustomerDaoException;
}

You didn't specify which language you are using, but regardless you may find this example using Java generics for DAO useful.

行至春深 2024-07-23 22:02:39

好的做法包括
为每个表创建一个类? 如果
那么,最佳实践是什么
将此类类加载/保存回
没有 orm 的数据库?

您正在使用 ORM。 您正在将对象映射到关系表。 是否使用预构建的库来执行此操作由您决定。 如果不这样做,您实际上将自己实现一个,尽管可能没有现有 ORM 的所有花哨功能。

执行此操作的两种最常见方法是 ActiveRecord 模式和数据映射器模式。 每个都有其优点和缺点。

使用 ActiveRecord 模式,您可以定义类,其属性为您定义表列。 此类的每个实例对应于数据库中的一行,通过创建(并保存)新实例,您可以在数据库中创建新行。 有关详细信息,请访问:http://en.wikipedia.org/wiki/Active_record_pattern

在数据映射器模式中,您为每个表定义表对象,并编写将表的列分配给现有类的映射器函数。 SQLAlchemy 默认使用此模式(尽管有 ActiveRecord 类型扩展模块,它们使 SQLAlchemy 的功能适应不同的接口。此模式的简要介绍可以在 SQLAlchemy 的文档中找到:http://www.sqlalchemy.org/docs/05/ormtutorial.html(从头开始阅读,但不包括标题为“以声明方式一次性创建表、类和映射器”的部分解释了使用 SQLAlchemy 的 ActiveRecord)

。在可读性方面有一个好处,ActiveRecord 类的声明性本质上可以有效地充当数据库模式的清晰、直接的文档,

数据映射器模式为您提供了更大的灵活性,让您能够更灵活地映射数据到类。与表和类之间或多或少的一对一关系无关。 它还将持久层与业务代码分开,这意味着您可以在以后根据需要更换其他持久机制。 这也意味着您可以更轻松地测试您的类,而无需设置数据库来支持它们。

有关 SQLAlchemy 映射器配置的更深入讨论,请查看 http://www.sqlalchemy。 org/docs/05/mappers.html。 即使您不打算使用像 SQLAlchemy 这样的库,文档也应该帮助您了解在将类映射到数据库表时可能需要考虑的一些选项。

Would good practice consist of
creating a class for each table? If
so, what are the best practices for
loading/saving such classes back to
the database without an orm?

You are using ORM. You are mapping objects to relational tables. Whether you use a pre-built library to do so or not is your call. If you don't, you'll be essentially implementing one yourself, though probably without all the bells and whistles of existing ORMs.

The two most common ways of doing this are the ActiveRecord pattern and the Data Mapper pattern. Each has its advantages and disadvantages.

With the ActiveRecord pattern, you define classes whose attributes define the table columns for you. Each instance of this class corresponds to a row in the database, and by creating (and saving) a new instance, you create a new row in the database. More information on that is available here: http://en.wikipedia.org/wiki/Active_record_pattern

In the Data Mapper pattern, you define table objects for each table, and write mapper functions which assign columns of the table to existing classes. SQLAlchemy uses this pattern by default (though there are ActiveRecord type extension modules, which adapt SQLAlchemy's functionality to a different interface. A brief introduction to this pattern can be found in SQLAlchemy's documentation here: http://www.sqlalchemy.org/docs/05/ormtutorial.html (read from the beginning up to but not including the section entitled, "Creating Table, Class and Mapper All at Once Declaratively;" that section explains ActiveRecord using SQLAlchemy).

The ActiveRecord pattern is easier to set up and get working with, and gives you classes which are clearly representative of your database, which has benefits in terms of readability. As a side benefit, the declarative nature of ActiveRecord classes effectively acts as clear and straightforward documentation for your database schema.

The Data Mapper pattern gives you far more flexibility in how your data maps to your classes, so you aren't tied to a more-or-less one-to-one relationship between tables and classes. It also separates your persistence layer from your business code, which means that you can swap out other persistence mechanisms later, if need be. It also means you can more easily test your classes without needing to have a database set up to back them.

For more in depth discussion of SQLAlchemy's mapper configuration, check out http://www.sqlalchemy.org/docs/05/mappers.html. Even if you aren't planning on using a library like SQLAlchemy, the documentation should help you see some of the options you may want to consider in mapping your classes to database tables.

三五鸿雁 2024-07-23 22:02:39

这种从数据库到类的观点方法很可能会导致您很快地编写大量代码。 然而,这段代码的很大一部分可能没有任何用处或者需要一些严重的修改。 换句话说,您可能会构建与您的显示和工作流程不匹配的特定类。

首先,考虑您的应用程序、用户的需求、一般工作流程等。实际上想出一些看起来可行的东西(即模拟您的显示器)。

专注于使用显示所需的类,并根据这些需求对存储进行建模(数据库设计)。 您可能只有几个直板类,因为您的大多数类自然会为您的显示提供解决方案。

祝你好运。

This DataBase to Class point of view approach is more than likely to lead you to cranking lots of code quite quickly. However, a good chunk of this code will likely not be of any use or require some severe mutation. In other words, you'll likely build specific classes that mismatch your displays and workflow.

First, consider your apps, your users' needs, general workflow .. etc Actually come up with something that looks workable (i.e. mock your displays).

Concentrate on the classes you need to use the displays and model your storage (db design) after those needs. Chances are that you will have only a few of straight-table classes as most of your classes will naturally tend provide the solution for your displays.

Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文