我使用Hibernate-Sessions错了吗?

时间:2015-07-15 09:31:38

标签: hibernate

现在我在代码审核上询问堆栈溢出this question上的that one

这让我想到如果我已经理解了如何使用Hibernate会话。我会尝试做这个简短的事情:

假设您有多种语言的工具和工具说明。因此,您有ToolToolDescriptionLanguage表。现在进一步假设您给客户提供了一组工具的可能性,但不仅仅是现有工具,他还可以通过创建一个新名称来创建新工具。当客户端将数据发送到服务器时,它会尝试存储这组工具,但必须先保存新工具。它看起来像这样:

客户发送:

ToolSet
  id:1
    Tool1
      id:2
        en:"My Hammer"
        de:"Mein Hammer"
    Tool2
      id:null
        en:"My new Tool"
        de:"Mein neues Werkzeug" 

要保存此功能,必须执行以下操作:(请注意,其中一个工具没有ID)。

toolSet = getToolSet(toolSetDto.getId());

if(toolSetDto.tool1 != null) {
    tool1Dto = toolDescriptionRepository.updateOrSaveNewTool(toolSetDto.getTool1());
}
if(toolSetDto.tool2 != null) {
    tool2Dto = toolDescriptionRepository.updateOrSaveNewTool(toolSetDto.getTool2());
}

// New session ..
session = Hibernate.openSession();
session.beginTransaction();
tool1 = session.get(Tool.class, tool1Dto.getId());
tool2 = session.get(Tool.class, tool2Dto.getId());
toolSet.setTool1(tool1);
toolSet.setTool2(tool2);
session.getTransaction().commit();
session.close();

对于updateOrSaveNewTool(ToolDTO toolDto)我们有类似的内容:

Session session = Hibernate.openSession();
Tool tool = null;

if(toolDto.getId() != null) {
  // Tool does already exist..
  tool = session.get(Tool.class, toolDto.getId());
} else {
  // Store a new tool ..
  session.beginTransaction();
  tool = new Tool();
  session.save(tool);
  ToolDescription toolDescription = new ToolDescription(tool, getDefaultLanguage());
  session.save(toolDescription);
  session.getTransaction().commit();
}

session.close();

这将在一个RPC调用中打开多个会话,例如由于我的问题,我有here我不确定我是否应该这样做。 我可以获得缓存问题吗?

有人可以向我解释一下如何使用Hibernate会话吗?我知道,他们应该执行/处理一个工作单元,但这并不能解释我是否应该为每个请求打开多个会话。

我当然可以 un 封装updateOrSaveNewTool()并且可以工作使用原始实体对象,并且不必在get(Tool.class, tool1Dto.getId())之后执行另一个updateOrSaveNewTool(),但这不会非常面向对象..

1 个答案:

答案 0 :(得分:1)

Hibernate会话应该被视为“工作单元”。如果您的工作单元涉及创建一些实体并稍后使用它们,那么最好对所有这些操作使用单个会话。更好的是,您将这些转换为单个事务,因此如果一个步骤失败,则回滚前面的步骤。 通常,工作单位是单个请求中发生的任何事情。

您所看到的是一个常见问题,根据您的技术堆栈,它会有所不同。

如果您在Java EE容器中,例如Wildfly,则可以让容器为您管理实体管理器。因此,您只需注入一个可以使用的EntityManager(即:“会话”已经为您打开,并且当您不再需要它时将关闭)。

另一种常见方法是每个请求使用一个会话,由您自己管理:您有一个过滤器(或类似的东西),一旦收到请求就会打开一个会话,并在响应准备就绪时关闭。您将其存储在本地线程中,以便每个请求都有自己的会话。

最后,如果您使用的是Spring,您可以将EntityManager的维护委派给它,就像您使用Java EE容器一样。