Java Servlet环境中的Hibernate使用

Java Servlet环境中的Hibernate使用,java,hibernate,annotations,Java,Hibernate,Annotations,我试图创建一个域对象,它以只读方式包含对象,但能够修改它指向的对象 因此,在下面的示例中,我希望Hibernate处理填充Account和Category对象,但我不想更新这些对象。但是,我可能希望更改我希望费用指向的帐户或类别 换句话说,我可能希望更新费用表上的帐户id或类别id,但我永远不希望使用我对费用对象中包含的帐户或类别对象所做的更改来更新帐户或类别表 @Entity @Table(name = "expense") public class Expense { @Id @G

我试图创建一个域对象,它以只读方式包含对象,但能够修改它指向的对象

因此,在下面的示例中,我希望Hibernate处理填充Account和Category对象,但我不想更新这些对象。但是,我可能希望更改我希望费用指向的帐户或类别

换句话说,我可能希望更新费用表上的帐户id或类别id,但我永远不希望使用我对费用对象中包含的帐户或类别对象所做的更改来更新帐户或类别表

@Entity
@Table(name = "expense")
public class Expense {

  @Id
  @GeneratedValue
  private long id;

  private String name;

  private BigDecimal amount;

  @OneToOne
  @JoinColumn(name = "id", referencedColumnName = "category_id")
  //From table called category
  private Category category;

  @OneToOne
  @JoinColumn(name = "id", referencedColumnName = "account_id")
  //From table called account
  private Account account;
我是完全误用了Hibernate还是它不是正确的工具?我应该用@SQLUpdate和@SQLInsert定义自己的sql吗

应用程序的一般流程是标准的web应用程序

  • 从数据库加载数据
  • 在表格上显示
  • 收集用户所做的更改
  • 坚持这些变化

  • 谢谢

    这有点偏离了hibernate的意图。对持久对象的更改应该是持久的。如果不想保存它们的状态,请不要更改它们!解释并更好地理解你为什么想要这种行为可能会帮助你找到解决方案(或者帮助我们帮助你)

    您可以选择在返回Expense对象之前分离/逐出不希望在数据访问层内更改的映射对象。然后,只要没有级联打开,对它们所做的更改就不会被保存。在我看来,这会导致其他程序员出现“令人惊讶”的行为

    另一种选择是以无会话方式使用hibernate。每个调用都是它自己的原子数据库操作,所有对象在返回后都被分离。然后,只有显式调用saveOrUpdate的实体才会保存到数据库中。您可以在Hibernate参考文档中学习如何配置Hibernate以这种方式工作,不过,我也不知道,如果您不尝试模拟正在提升的某些遗留系统的行为,您为什么要这样做

    最后一点需要理解的是,在会话中,通过调用expense.getCategory()得到的类别通常与通过调用Session.get(Category.class,123)得到的实际对象相同。因此,如果在同一个会话中有两种访问它的方法,那么如果您试图手动管理它,就很容易失去对其实体状态的跟踪


    编辑:

    啊哈!现在它更有意义了

    如果你做的是纯粹粗糙的web表单屏幕,你不必担心太多。只要没有任何层叠,当您合并回分离的
    费用
    对象时,
    类别
    帐户
    上的更改就不会在数据库中结束。您可以将其他字段清空,只要id仍然存在,就可以了。(假设您没有其他类似级联验证的东西会为此哭泣。)

    有两种基本模式可以更好地处理这个问题

    一种是将
    Expense
    对象放在用户的web会话上。这样,您就拥有了整个内容,您的web数据绑定框架只需要将表单实际更改的字段绑定回它。原始的
    类别
    帐户
    仍然存在(或它们的代理),活页夹不需要咀嚼它们。缺点当然是添加服务器端状态,并且需要清理它

    二是注册实际进入数据库的数据绑定,并在web绑定期间获取映射实体。因此,表单中实际出现的只是映射字段的ID,绑定器将为您获取并放置完整的对象。缺点可能是不需要来回访问数据库,但积极的二级缓存可以解决这一问题(假设类别几乎从不更改,帐户很少更改)


    如果您目前通过在DAO中创建和处理会话,以基本上无会话的方式使用hibernate,那么您可能还需要查看OpenSessionInView/OpenEntityManagerView模式。

    我在servlet环境中工作,因此我的hibernate会话只会持续到我在应用程序的DAO层。该流程是一个标准的web应用程序
    从Hibernate加载数据->在表单上显示内容->从表单获取数据->将数据加载回数据库。
    从表单返回后,我不一定拥有Hibernate最初提供给我的完整对象,只需要一些零碎的东西。所以我不想用这些片段覆盖数据库中的完整对象。这正是我想要的。很抱歉,花了这么长时间才恢复。谢谢