Hibernate 查找表:作为对象关系或作为代码/键

发布于 2024-12-05 08:59:17 字数 1761 浏览 2 评论 0原文

因此,我正在开发一个包含大量关系和查找表的应用程序,但这一切都归结为:

Person

id INT (PK)
... (name, address, etc)
optcode VARCHAR (FK to Options)
typecode VARCHAR (FK to Types)

Options

optcode VARCHAR (PK)
optdesc VARCHAR
... (more meta data, like date added, etc)

Types

code VARCHAR (PK)
desc VARCHAR
... (more meta data, like date added, etc)

I我正在使用 hibernate 来访问这些表,一方面,对象关系有好处,但另一方面,仅使用字符串来编写代码效果更好。

对象关系、键和两者哪个更好?

仅使用键:

public class Person {
     private int id;
     ... (more attributes)
     private String optcode;
     private String typecode;
}
In the services:
Person person = new Person();
person.setOptcode("ABC");
person.setTypecode("XYZ");
session.save(person);

或 O/R 方式:

public class Person {
     private int id;
     ... (more attributes)
     @JoinColumn
     private Options option;
     @JoinColumn
     private Types type;
}
In the services:
Person person = new Person();
person.setOption(new Options("ABC")); //Assume constructor fills in the 'optcode'
person.setType(new Types("XYZ"));     //Same, with 'code'
session.save(person);

在大多数持久性情况下,我只有“代码”,但很多时候在显示数据时,显示“描述”会很好,

因为我将有一个地方可以管理选项和类型实体,这些实体无论如何都会存在,但必须将“代码”包装在对象中只是很烦人。

您认为不同方式的优点/缺点是什么?如果我只是将两者都放入 Person 对象中,这样我就可以使用更方便的那个了,会怎么样?如何制作仅将字符串推入新的选项/类型实体的设置器?

我正在尝试确定最佳方法,以便保持一致,现在我只是在做任何需要最少数量新实体的事情,但最终所有内容都将由休眠实体表示。

更新: Person 实体最终将拥有近 20 个唯一的实体关系(每个实体关系都指向不同的表),Web-ui 可能会有包含每个表的值的下拉列表,因此我希望我只有用于持久性的“代码”。 相关:我实际上使用的是 PersonImpl(普通 POJO)和 PersonEntity(Hibernate Entity)以及 Dozer 映射之间的关系。

So, I'm working on an application with lots of relations and lookup tables, but It all boils down to this:

Person

id INT (PK)
... (name, address, etc)
optcode VARCHAR (FK to Options)
typecode VARCHAR (FK to Types)

Options

optcode VARCHAR (PK)
optdesc VARCHAR
... (more meta data, like date added, etc)

Types

code VARCHAR (PK)
desc VARCHAR
... (more meta data, like date added, etc)

I'm using hibernate to access these tables and on the one hand, Object Relations have benefits, but on the other hand, just using Strings for the codes works better.

What is better Object Relations vs Keys vs both?

Just using Keys:

public class Person {
     private int id;
     ... (more attributes)
     private String optcode;
     private String typecode;
}
In the services:
Person person = new Person();
person.setOptcode("ABC");
person.setTypecode("XYZ");
session.save(person);

Or the O/R way:

public class Person {
     private int id;
     ... (more attributes)
     @JoinColumn
     private Options option;
     @JoinColumn
     private Types type;
}
In the services:
Person person = new Person();
person.setOption(new Options("ABC")); //Assume constructor fills in the 'optcode'
person.setType(new Types("XYZ"));     //Same, with 'code'
session.save(person);

In most cases of persistence, I only have the 'code', but many times when displaying the data it would be nice to show the 'desc'

Since I'll have a place to manage the Options and Types entities, those will exist anyways, but it just is annoying to have to wrap the 'code' in an object.

What do you think are the pros/cons of the different ways? What if I just put both into the Person object so i can use what ever is more convinent? What about making setters that just shove the string into a new Options/Types entity?

I'm trying to pin down the best way so it can be consistent, right now I've just been doing whatever required the least amount of new entities, but eventually everything will be represented by hibernate entities.

Update: The Person Entity will end up having almost 20 unique entity relations (each one pointing to a different table), The web-ui will probably have drop-down lists containing the values for each table, so I expect that I'll only have the 'code' to use for persistence.
Related: I'm actually using a PersonImpl (plain POJO) and a PersonEntity (Hibernate Entity) and Dozer Mapping to go between.

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

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

发布评论

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

评论(4

樱桃奶球 2024-12-12 08:59:17

ORM 的全部意义在于为您提供一个对象图,您可以在其中导航,并映射到关系数据库。您应该能够使用 person.getOption().getDescription() 从人员那里获取其选项描述。

您还应该能够使用给定选项日期来搜索人员。

select p from Person p where p.option.date = :date

这只有在将外键映射为关联而不是字符串时才可能实现。

不过,您不应该使用 new Option(code) 将现有选项放入您的用户中。相反,您应该从会话中获取或加载选项:

Person p = new Person();
p.setOption((Option) session.load(Option.class, "ABC"));
p.setType((Type) session.load(Type.class, "XYZ"));
session.save(p);

// and now, this code works as expected:
System.out.println(p.getOption().getDescription());

The whole point of an ORM is to give you an object graph, in which you can navigate, and which maps to a relational database. From a person, you should be able to get its option description using person.getOption().getDescription().

You should also be able to search for persons with a given option date using

select p from Person p where p.option.date = :date

This is only possible if you map the foreign key as an association, rather than a String.

You should not use new Option(code) to put an existing option into your person, thouh. Instead, you should get or load the option from the session:

Person p = new Person();
p.setOption((Option) session.load(Option.class, "ABC"));
p.setType((Type) session.load(Type.class, "XYZ"));
session.save(p);

// and now, this code works as expected:
System.out.println(p.getOption().getDescription());
锦上情书 2024-12-12 08:59:17

我认为实体关系使您的编码更容易,一般来说,尤其是在查询对象时:有什么比说 person.getOption().getDescription() 更容易?然而,这种方法确实有缺点:

  • 必须从数据库加载引用的实体,特别是当您有保存级联时。在保存级联中,您可能知道,Hibernate 会抱怨数据库中存在该对象。我不确定当你没有保存级联时会发生什么。
  • 引用的实体必须使用单独的查询或在加载主实体时使用外部联接来加载。 可能导致性能问题。

将键保留为纯粹的属性可以在复杂关系的情况下有所帮助,例如,当引用一个需要由 Hibernate 完成大量负载的实体时。这种方法可以帮助系统更轻松地加载“主”实体。这确实意味着如果您需要实体的属性,您将必须自己加载实体。我想说,对于不可变的“查找”类型实体,您可以安全地保留其实例的内存映射并通过其密钥 get() 它们,而不是访问数据库。缺点是您将划分实体处理逻辑:您必须记住要缓存哪些实体并管理它们的缓存。

我想说,一般来说,与实体合作总是更好,毕竟这是你的模型。 Hibernate 坚持指出它可以帮助你持久化你的对象模型来帮助你。那么将尽可能多的持久性工作委托给 Hibernate 是合乎逻辑的。然而,在某些情况下,Hibernate 无法很好地处理“适当”模型:具有许多关系的实体、一直使用的“热门”实体等。在这些情况下,如果Hibernate 的机制无济于事(例如二级缓存),您确实必须求助于此类“技巧”并自己完成一些工作。

I think entity relations make your coding easier, generally speaking, especially when querying for objects: what's easier than saying person.getOption().getDescription()? This approach does have drawbacks, however:

  • Referenced entities have to be loaded from the DB, especially when you have save-cascade. In save-cascade, as you probably know, Hibernate will complain the object exists in the DB. I'm not sure what happens when you don't have save-cascade.
  • Referenced entities have to be loaded with either a separate query, or an outer join on the loading of the main entity. Can cause performance problems.

Persisting the keys as mere properties can help in cases of complex relationships, for example when referencing a big entity with much loading to be done by Hibernate. This approach can help make loading the "master" entity lighter for the system. It does mean that you will have to do the entity loading yourself, if you need its properties. I'd say that for immutable "look-up" type entities, you could safely keep an in-memory Map of their instances and get() them by their key, instead of going to the DB. The down-side is that you will partition your entity-handling logic: you will have to remember which entities to cache and manage their caches.

I'd say that, in general, it's always better to work with entities, which is your model after all. Hibernate insists in noting that it helps you persist your object model to help you. It is only logical to delegate as much of the persistence stuff to Hibernate then. There are cases however, that Hibernate can't cope very well with a "proper" model: entities with many relations, "hot" entities that get used all the time, etc. In these cases, if Hibernate's mechanisms can't help (2nd level cache for example) you really have to resort to such "tricks" and do some of the work yourself.

〆凄凉。 2024-12-12 08:59:17

我想我只会在表具有很多相同结构(“代码”、“描述”等)的情况下使用 Hibernate 的 @MappedSuperclass,这样我就可以减少代码行数。但除此之外,O/R 似乎是一条出路。

I guess I'll just use Hibernate's @MappedSuperclass for cases where tables have alot of the same structure ('code' ,'description', etc) so that I can keep the # of lines of code down. But otherwise O/R seems to be the way to go.

离旧人 2024-12-12 08:59:17

我遇到这个问题是因为我想知道人们在遇到需要查找其他实体的实体时会做什么。这样做的主要问题是,即使在测试中,您也不能再仅仅创建实例。我的首选方法是转向工厂或外部(例如非静态类)构建器。

总体而言,我遇到的问题是它非常基础,并且涉及很多容易出错的样板文件。例如,假设我有一个名为“列表”的内容,我必须跟踪它的来源(我在哪里找到它)。源是一个非常简单的实体,但现在我在列表中引用了它,如果不查找源然后注入适当的源,我就无法再创建列表。

如果可能的话,通过简单的注释来处理这个问题是有意义的,例如诸如mappedBy之类的东西,但引用id或name,然后容器可以进行查找和注入。

不过,我们很快就会看到这一点。

I came across this question because I was wondering what people were doing once they hit upon entities that required the lookup of other entities. The primary problem with that is that then you can no longer just create an instance, even in a test. My preferred approach is to move to either a Factory or an external (e.g. not static class) Builder.

The problem I have with this overall though is that it's very basic, and there is a lot of error-prone boilerplate involved. For example, suppose I have a piece of content, called Listing and I have to track the Source it came from (where I found it). The source is a very simple entity, but now that I have a reference to it inside Listing, I can no longer create Listings without doing the lookup of the source and then the injection of the appropriate one.

It would make sense, if possible, to handle this through simple annotations, e.g. something like mappedBy, but referring to either id or name, and then the container could do the lookup and the injection.

Doubt we'll see this anytime soon, though..

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