简体   繁体   English

使用Spring在Hibernate中进行会话处理

[英]Session handling in Hibernate with Spring

I am not a beginner in hibernate, but I am a beginner in working with Hibernate in Spring. 我不是hibernate的初学者,但是我是Spring中与Hibernate合作的初学者。 I read the book Spring in Action. 我读了《 Spring in Action》一书。 So I wrote a small application to comprehend the examples in the book. 因此,我编写了一个小应用程序来理解本书中的示例。 Here an extraction of my application. 这里是我的应用程序的摘录。 I can give you more, if you want. 如果您愿意,我可以给您更多。

@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public void runQuery()
{
    final BuildingDAO buildingDAO = ( BuildingDAO ) applContext.getBean( "buildingDAO" );
    final Building building = buildingDAO.getBuildingById( "HQ" );
    logger.debug( "Loaded building: " + building.getId() );
    logger.debug( "Loaded building: " + building.getName() );
}

The object is loaded without any problems. 该对象已加载,没有任何问题。 The log of the Primary-Key is no problem, too. 主键的日志也没有问题。 But the log of the string attribute causes a LazyInitializationException. 但是字符串属性的日志会导致LazyInitializationException。 I understand why this happens. 我知道为什么会这样。 Hibernate returned a proxy with proxied atributes. Hibernate返回了带有代理属性的代理。 When I want to access to a lazy-loaded attribute, Hibernate tried to load the value but the session is closed. 当我想访问延迟加载的属性时,Hibernate尝试加载该值,但会话已关闭。 Lazy loading is a great feature of Hibernate and I don't want to miss it. 延迟加载是Hibernate的一项重要功能,我不想错过它。

Spring manages the session-handling for me. Spring为我管理会话处理。 Spring opens a Hibernate session in the load-method of the Hibernate-template and closes the session after the method has finished. Spring在Hibernate模板的加载方法中打开一个Hibernate会话,并在方法完成后关闭该会话。

But now I want to advise Spring that the session should be open in the whole method (runQuery()), which is shown above. 但是现在我想建议Spring在整个方法(runQuery())中打开会话,如上所示。 I want to display some attributes of the object. 我想显示对象的一些属性。 I mentioned I can use a tranaction-manager of Spring to do that. 我提到我可以使用Spring的事务管理器来做到这一点。 So I use the Transactional-Annotation of Spring. 因此,我使用Spring的事务注释。 But it doesn't work. 但这是行不通的。 Maybe my assumption to use the transaction-manager is wrong. 也许我的假设使用事务管理器是错误的。

Has anybody an idea to advise Spring to hold open a session for the whole method? 有没有人建议Spring为整个方法举行一次会议?

Are you sure Propagation.SUPPORTS is what you really need? 您确定您确实需要Propagation.SUPPORTS吗? That doesn't enforce the presense of a transaction, it just uses it if it's there. 那不会强制事务的存在,它只是在有事务的情况下使用它。 Some other part of the system needs to be starting and committing the transaction. 系统的其他部分需要启动和提交事务。 If none is present, then the session may not be maintained as far as your log statements, resulting in a lazy load error. 如果不存在,则会话可能无法维护到您的日志语句为止,从而导致延迟加载错误。

Try using some other isolation level (like REQUIRED, or better yet, don't specify it all, and rely on the default) and see if that fixes your problem. 尝试使用其他一些隔离级别(例如“必需”,或者更好,不要全部指定它,而是依靠默认值),看看是否可以解决您的问题。

Changing to REQUIRED or just leaving it blank, will fix your problem. 更改为“必需”或仅将其留为空白将解决您的问题。 Propagation.SUPPORTS does not actually start a transaction... see http://www.ibm.com/developerworks/java/library/j-ts2.html Propagation.SUPPORTS实际上并未启动交易...请参阅http://www.ibm.com/developerworks/java/library/j-ts2.html

You probably haven't disabled non transactional reads (the default is enabled) and thus the read is successful, but the transaction for that read is only for the read itself (not for subsequent reads on the object returned). 您可能没有禁用非事务性读取(默认启用),因此读取成功,但是该读取的事务仅针对读取本身(不适用于返回的对象的后续读取)。

The category for logging on transaction activity is org.springframework.transaction IIRC - if you turn this to DEBUG and you'll see details of when transactions are started and committed. 登录事务活动的类别是org.springframework.transaction IIRC-如果将其转到DEBUG,则将看到有关启动和提交事务的详细信息。

If you want RunQuery to run inside a Spring transaction, you have to get an object of the class defining it as a spring bean from the container. 如果希望RunQuery在Spring事务中运行,则必须从容器中获取将其定义为Spring Bean的类的对象。 That way Spring can wrap transactional logic around the bean (And whatever methods it defines). 这样,Spring可以将事务逻辑包装在bean周围(以及它定义的任何方法)。
Defining that class as a spring bean will also save you from calling to (BuildingDAO)applContext.getBean("buildingDAO") because spring will wire the dao into your class (if you define it properly in the context xml or attributes). 将该类定义为spring bean还将使您(BuildingDAO)applContext.getBean("buildingDAO")调用(BuildingDAO)applContext.getBean("buildingDAO")因为spring会将dao连接到您的类中(如果您在上下文xml或属性中正确定义了该类)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM