使用实体管理器关闭Hibernate会话

时间:2011-07-25 18:55:40

标签: hibernate spring jpa

我正在开发一个软件的一部分,它有两个模块(邮件和网络服务)。但我的代码中有一些混乱,我认为我的方式错误/做得不好/困难。有人可以帮我克服这些吗?问题是hibernate正在关闭会话。

这是我的pom结构

 -- root
    -- mail
    -- web-service

需要注意的是,我的spring bootstrapping,appContext.xml,持久化上下文都是托管我的web服务模块,我在我的web服务模块中使用邮件模块作为依赖jar。

我的appContext.xml是这样的,

<context:component-scan base-package="com.it.ese.orbitws,com.it.ese.orbitmail" />

<context:annotation-config />
<tx:annotation-driven />


<!-- enables interpretation of the @PersistenceUnit/@PersistenceContext annotations providing convenient
 access to EntityManagerFactory/EntityManager -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>


 <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
    <property name="url" value="jdbc:sqlserver://localhost:1433;database=ORBIT_RC" />
    <property name="username" value="sa" />
    <property name="password" value="sa" />
</bean>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect" />
            <property name="showSql" value="true" />
        </bean>
    </property>
    <property name="dataSource" ref="dataSource" />
</bean>


 <bean id="transactionManager"
    class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory"
              ref="entityManagerFactory" />
        <qualifier value="tx"/>
  </bean>

我想让邮件模块尽可能独立。邮件配置也来自数据库表:

table : "custom":(smtp,global_sender)

所以我创建了自己的JavaMailSenderImpl,我在这里覆盖了这样的getHost方法。我把它作为spring @Component。我的困惑在于代码中的注释。

package com.it.ese.mail
@Component 
public class OrbitJavaMailSenderImpl extends JavaMailSenderImpl{


 private EntityManager entityManager;
 private String smtp=null;

 private OrbitJavaMailSenderImpl() {
 }

 // I have used  PersistenceContextType.EXTENDED because without this,it says
 // Hibernate Session is closed.But using EXTENDED is a bad thing?or it's ok?  

 @PersistenceContext (type= PersistenceContextType.EXTENDED)
 public void setEntityManager(EntityManager entityManager) {
     this.entityManager = entityManager;
 }

 //There is no Bean for CUStom TABLE so far in persistence.xml.Should I do that too?

 @Transactional(readOnly=true)
 public String getSMTPAddress() {
    String host="mail.esolutionss-europe.com";
    try{
        host= this.entityManager.createNativeQuery("SELECT smtp FROM CUSTOM")
                .getSingleResult().toString();
    }catch(Exception e){
        System.out.println("error getting host:"+e.toString());

    }

    return host;
}

}

在网络服务模块中,我有一个服务NotificationService,我正在注入春季邮件服务。

package com.it.ese.ws.service 
public class NotificationService implements INotificationService {

private EntityManager entityManager;
private String sender=null;

final static Logger logger = Logger.getLogger(NotificationService.class);

@PersistenceContext (type= PersistenceContextType.EXTENDED)
public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}


//Also here if I don't use EXTENTED persistence context,it gives me error as hibernate session is closed.

@Transactional(readOnly=true)
public String getGlobalSender() {
    String sender="a1@xxx.com";
    try{
        sender= entityManager.createNativeQuery("SELECT Global_email FROM CUSTOM")
                .getSingleResult().toString();
    }catch(Exception e){

    }
    return sender;
} /*other methods*/ }

为什么我的EntityManager会关闭?这个Container管理好了吗?是什么导致了封闭的选择?

2 个答案:

答案 0 :(得分:2)

不要使用PersistenceContextType.EXTENDED(除非你非常清楚自己在做什么)。 See here有详细解释。

答案 1 :(得分:2)

我找到了解决方案。我犯了一个错误。我做的是我有一个像

这样的方法
public String getX(){
   return getY()
}

从getX我调用getY,其中有@Transactional我实际使用的是Entity Manager。 问题是我没有使用@Transactional所以它说会话已关闭。 现在我确实喜欢,

@Transactional 
public String getX(){  //getX() is just a wrapper for some reason :)
  return getY(); 
} 

现在一切顺利。但这是正当理由还是其他什么?