2

我有一个与用户对象(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;
    }
    //....
}
4

3 回答 3

1

使用EntityListener@PostLoad回调方法:

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

更新(基于以下评论):

我可以理解想从内存中加载实例;我不明白你为什么要让Hibernate这样做:-) 这一切都归结为一个简单的选择——要么你的User实体至少有一些你希望始终坚持到/从数据库加载的字段,要么它没有。我认为我们正在谈论后一种情况,因为我上面提出的解决方案最好地服务于前者。然后,您的选择归结为:

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

  2. 您可以编写一个自定义类型,为您自动执行上述操作。如果您有很多引用用户的实体(您将避免重复代码),这可能是有道理的。您需要实现UserType接口;您将根据从 ResultSet 中传递的标识符User从方法中从缓存中检索您的实例;nullSafeGet()你会做相反的事情nullSageSet()并坚持下去。

于 2009-09-07T19:38:42.683 回答
0

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

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

我真的想像持久化字段一样处理它,你应该查看休眠事件模型,找到需要实现的事件才能插入你的逻辑。但如果你想实现一个或多或少完整的持久性解决方案,它持久化在与 DB 或 XML 文件不同的东西中。

于 2009-09-07T19:22:41.823 回答
0

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

在根据需要持久化用户的同时,您当然可以在不加载用户实体的情况下查询消息。我会做的是 UserId 字段(“to”和“from”,如果我理解正确的话),输入 Long。所以说什么用户相关的信息就在那里。

现在,要获取实际的用户实体:

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

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

  • 或者,您让其他代码(服务等)使用 UserId 通过调用适当的服务(封装 Map)通过 UserId 获取用户实例。
于 2009-09-07T19:35:57.507 回答