从外部源加载 Hibernate 属性 (HashMap)

发布于 2024-08-04 06:47:22 字数 2304 浏览 4 评论 0原文

我有一个与用户对象(user_from 和 user_to)关联的消息对象。我使用 Hibernate(带有 JPA 注释)将 Message 实例持久保存到数据库中,并且 user_id 也被持久保存。

User 对象也存储到数据库中,但是在获取消息时,我希望从内存中的 Map 而不是从数据库中获取 User。

原因是因为我有一些临时属性,无法持久保存到数据库(Facebook 数据),并且当 Facebook 数据已经加载到内存中时,我不想重新查询 Facebook 的数据。

这是否可能或应该通过创建 UserType 来完成?哪个类需要定义为 UserType、Message、User 或自定义映射器?如果是自定义映射器,如何使用 JPA 注释关联映射器(我见过一个使用配置并设置 meta-type="com.example.hibernate.customtype.CustomerTypeMapper" 的示例)?

非常感谢您的帮助!

用户类别:

@Entity(name="com.company.model.user")
@Table(name = "user")
public class User {
    private Long id;
    private Long fbId;
    private String firstName;
    private URL picThumbnailUrl;
    //...

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Long getFbId() {
        return fbId;
    }
    public void setFbId(Long fbId) {
        this.fbId = fbId;
    }
    @Transient @FacebookField
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    @Transient @FacebookField
    public URL getPicThumbnailUrl() {
        return picThumbnailUrl;
    }
    public void setPicThumbnailUrl(URL picThumbnailUrl) {
        this.picThumbnailUrl = picThumbnailUrl;
    }
    //....
}

消息类别:

@Entity(name="com.company.model.message")
@Table(name = "message")
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @ManyToOne
    @JoinColumn(name="user_id_from")
    private User from;
    @ManyToOne
    @JoinColumn(name="user_id_to")
    private User to;
    private String text;
    //...

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public User getFrom() {
        return from;
    }
    public void setFrom(User from) {
        this.from = from;
    }
    public User getTo() {
        return to;
    }
    public void setTo(User to) {
        this.to = to;
    }
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
    //....
}

I have a Message object associated with a User object (user_from and user_to). I persist the Message instances into a database using Hibernate (with JPA annotations) and the user_id is persisted.

The User object is also stored to the database, but when fetching messages I would like the User to be fetched from a Map in memory instead of from the database.

The reason is because I have some transient attributes that I can't persist to the database (Facebook data), and when the Facebook data is already loaded in memory, I don't want to re-query Facebook for the data.

Is this possible or should be done by creating a UserType? Which class needs to be defined as the UserType, the Message, the User or a custom mapper? If a custom mapper, how do I associate the mapper using JPA annotations (I have seen an example that uses configurations and sets meta-type="com.example.hibernate.customtype.CustomerTypeMapper")?

Thank you very much for your help!

User class:

@Entity(name="com.company.model.user")
@Table(name = "user")
public class User {
    private Long id;
    private Long fbId;
    private String firstName;
    private URL picThumbnailUrl;
    //...

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Long getFbId() {
        return fbId;
    }
    public void setFbId(Long fbId) {
        this.fbId = fbId;
    }
    @Transient @FacebookField
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    @Transient @FacebookField
    public URL getPicThumbnailUrl() {
        return picThumbnailUrl;
    }
    public void setPicThumbnailUrl(URL picThumbnailUrl) {
        this.picThumbnailUrl = picThumbnailUrl;
    }
    //....
}

Message class:

@Entity(name="com.company.model.message")
@Table(name = "message")
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @ManyToOne
    @JoinColumn(name="user_id_from")
    private User from;
    @ManyToOne
    @JoinColumn(name="user_id_to")
    private User to;
    private String text;
    //...

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public User getFrom() {
        return from;
    }
    public void setFrom(User from) {
        this.from = from;
    }
    public User getTo() {
        return to;
    }
    public void setTo(User to) {
        this.to = to;
    }
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
    //....
}

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

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

发布评论

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

评论(3

樱娆 2024-08-11 06:47:22

使用 EntityListener@PostLoad 回调方法:

@PostLoad
public void updateFacebookFields() {
  // get stuff from HashMap
  setFirstName("whatever");
  setPicThumbnailUrl(myUrl);
}

更新(基于下面的注释):

我可以理解想要从内存中加载实例;我不明白为什么您希望 Hibernate 执行此操作:-) 这一切实际上都归结为一个简单的选择 - 要么您的 User 实体至少有一些字段您希望始终坚持到数据库/从数据库加载,否则不会。我认为我们正在讨论后一种情况,因为前一种情况最适合我上面提出的解决方案。您的选择归结为:

  1. 根本不保留User。任何引用它的实体都只会保留用户标识符;您将使用适当的 getter 方法从缓存中检索实际的用户实例。

  2. 您可以编写一个自定义类型来自动执行上述操作。如果您有大量引用用户的实体,这可能是有意义的(您将避免重复的代码)。您需要实现 UserType 接口;您将根据在 ResultSet 中传递的标识符,在 nullSafeGet() 方法中从缓存中检索您的 User 实例;您将在 nullSageSet() 中执行相反的操作并将其保留回来。

Use an EntityListener or a @PostLoad callback method:

@PostLoad
public void updateFacebookFields() {
  // get stuff from HashMap
  setFirstName("whatever");
  setPicThumbnailUrl(myUrl);
}

Update (based on comments below):

I can understand you wanting to load instance from memory; I don't understand why you'd want Hibernate to do it :-) It all really comes down to a simple choice - either your User entity has at least some fields you'd want to always persist to / load from the database or it doesn't. I take it we're talking about the latter scenario because the former is best served by the solution I've proposed above. Your choices then boil down to:

  1. Not persisting User at all. Any entity referencing it would persist only user identifier; you will retrieve the actual user instance from your cache in appropriate getter method.

  2. You can write a custom type that would automate the above for you. That may make sense if you have lots of entities referencing users (you'll avoid repeated code). You'll need to implement UserType interface; you'll retrieve your User instance from your cache from within nullSafeGet() method based on identifier you get from passed in ResultSet; you'll do the opposite in nullSageSet() and persist it back.

一个人的旅程 2024-08-11 06:47:22

我认为用户类型在这种情况下没有帮助。用户类型更多地用于指定数据如何保存在数据库中,而不是是否。

最简单的解决方案可能是将您的字段标记为瞬态,并让 getter 从某个服务获取此数据,该服务反过来会检查内部缓存,如果缓存未命中,则实际查询 facebook。

如果你真的想像持久化字段一样处理它,你应该检查休眠事件模型,找到你需要实现的事件,以便插入你的逻辑。但是如果你想实现一个或多或少完整的持久性解决方案,它以不同于数据库或 XML 文件的方式持久化。

I don't think user type would help in this case. A User Type is more for specifying how data gets saved in the database not if.

Probably the easiest solution would be to mark your field as transient, and let the getter fetch this data from some service which in turn would check an internal cache and in case of a cache miss actually query facebook.

I you really want to handle it like a persisted field you should check out the hibernate event model, to find the events that you need to implement in order to plug your logic in. But this would be more use full if you want to implement a more or less complete persistence solution that persists in something different then DBs or XML files.

终遇你 2024-08-11 06:47:22

使用简单性原则,我首先提出以下建议:

在根据需要保留用户时,您当然可以在不加载用户实体的情况下查询消息。
我要做的就是拥有输入为 Long 的 UserId 字段(如果我理解正确的话,为“to”和“from”)。因此,说明哪些用户相关的信息就在那里。

现在,要获取实际的 User 实体:

  • 您可以创建一个备用 getter(瞬态的,对于 Hibernate 来说是非映射的),它将通过查看您的 Map 来提供 User 实例。

通常会限制域模型对象(此处为持久实体)访问服务和其他代码。因此,要么将地图作为模型的一部分(它可以静态存储在模型类中)。

  • 或者,您可以让其他代码(服务等)使用 UserId,通过调用适当的 Service(封装 Map)来通过 UserId 获取 User 实例。

Using the principle of simplicity, I would start with suggesting the following:

While persisting Users as needed, you can certainly query for Messages without loading Users entities.
What I would do would have UserId fields ("to" and "from" if I understand correctly), that are typed Long. So the information saying what user is related is there.

Now, to obtain the actual User entity:

  • You could make an alternate getter (transient, non mapped for Hibernate) that would provide the User instance by looking into your Map.

It is typical to restrict domain model objects (a persistent entity here) from accessing to services and other codes. Therefore, either you make the map part of your model (it could be statically stored in a model class).

  • Or, you let other codes (Services etc) use the UserId to obtain the User instance via the UserId, by calling the appropriate Service (that encapsulates the Map).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文