2016-12-17 3 views
-2

В моем приложении мы имеем следующую архитектуру:Spring EJB Integration

  • Web Layer: JSF + Rich Faces
  • Service Layer: EJB
  • DAO Layer: EJB Классы [состоят из JDBC запросов]

Мы хотим использовать Hibernate в качестве рамки ORM вместо JDBC в слое DAO. Я хочу использовать функцию Spring ORM для интеграции Hibernate в слой DAO. Теперь проблемы, с которыми мы сталкиваемся:

Классы уровня DAO являются классами EJB без гражданства. Таким образом, чтобы использовать Spring DI внутри классов EJB, я должен идти на перехватчик следующим образом:

@Stateless(mappedName = "myAppDao") 
@Interceptors(SpringBeanAutowiringInterceptor.class) 
public class MyAppDaoImpl implements MyAppDaoRemote { 

@Autowired 
private SessionFactory sessionFactory; 

@Override 
public void getSession() { 
    if(sessionFactory!=null){ 
     Session session = null; 
     try{ 
      session = sessionFactory.getCurrentSession(); 
     }catch (Exception e) { 
      session = sessionFactory.openSession(); 
      System.out.println("Exception:"+e.getMessage()); 
     } 
} 

С sessionFactory.getCurrentSession() Я получаю это исключение:

Исключение: Не удалось получить транзакции синхронизированные сессии для текущей нити.

Причина, по которой я не могу использовать Spring-транзакцию на уровне сервиса, так как у меня есть классы EJB на моем уровне обслуживания.

Кроме того, я не хочу использовать sessionFactory.openSession(), так как в этом случае мне пришлось бы вручную закрыть сеанс.

Это мои пружинные конфигурационные файлы:

1) beanRefContext.xml -> используемые перехватчики

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context" 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> 

    <bean id="businessBeanFctory" class="org.springframework.context.support.ClassPathXmlApplicationContext"> 
      <constructor-arg value="classpath*:daoConfig.xml" /> 
    </bean> 
</beans> 

2) daoConfig.xml -> Конфигурация Hibernate

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd 
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="packagesToScan" value="com.myapp.model"/> 
     <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> 
      <prop key="hibernate.show_sql">false</prop> 
      </props> 
     </property> 
    </bean> 

    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyAppDS" expected-type="javax.sql.DataSource"/> 

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>  
    <tx:annotation-driven transaction-manager="transactionManager" /> 

    </beans> 

Я знаю, что нет смысла использовать EJB вместе с Spring, поскольку они чередуются друг с другом. Но из-за некоторого ограничения на уровне проекта я пока не могу удалить EJB.

Итак, есть ли какое-либо решение, с помощью которого мы можем получить текущую сессию Hibernate внутри класса EJB через Spring?

+1

«Мы хотим использовать Hibernate как ORM Framework вместо JDBC в DAO Layer. Я хочу использовать функцию Spring ORM для интеграции Hibernate в DAO Layer». - Возможно, я не понимаю, но если основной целью является использование Hibernate в вашем DAO-слое, который состоит из классов EJB, то почему бы не попытаться напрямую интегрировать EJB с Hibernate, почему Spring добавляется к картинке? – hammerfest

+0

Я хочу добавить Spring beacause, если я использую Hibernate только через файл hibernate.cfg.config.xml, тогда мне нужно позаботиться о том, чтобы открыть и закрыть транзакцию, а также выполнить операцию фиксации с уровня кода (transaction.commit). Я хочу управлять всеми этими вещами через контейнер Spring. –

ответ

0

Если вы используете JBossAS/WildFly то вам просто необходимо:

@Stateless(mappedName = "myAppDao") 
public class MyAppDaoImpl implements MyAppDaoRemote { 

    @PersistenceContext 
    private Session session; 

    public void someDaoMethod(YourEntity e) { 
     // use session directly 
     // Transactions are automatically managed by the EJB container 
     // because that's one of EJB's raison d'être 
    } 

} 

Убедитесь, что ваш (традиционный) Hibernate конфигурация определяет JTA транзакции.

Для получения дополнительной информации см. WildFly JPA Reference Guide.

Если вы не используете один из этих реализаций JavaEE, то вы все еще можете использовать конфигурацию Spring, что у вас есть, но не забудьте включить:

<property name="jtaTransactionManager" value="transactionManager"/> 

в вашем sessionFactory боба.

Кроме того, если вы используете WebLogic или WebSphere, вам может потребоваться указать управляющие транзакциями JTA на платформе для этих серверов, например WebLogicJtaTransactionManager или org.springframework.transaction.jta.WebSphereUowTransactionManager.

0

Я изменил свой daoConfig.xml следующим способом

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:p="http://www.springframework.org/schema/p" 
xmlns:jee="http://www.springframework.org/schema/jee" 
xmlns:tx="http://www.springframework.org/schema/tx" 
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd 
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> 

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="packagesToScan" value="com.oms.model"/> 
    <property name="jtaTransactionManager" ref="transactionManager"/> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> 
      <prop key="hibernate.show_sql">true</prop> 
     </props> 
    </property> 
</bean> 

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/OMSDS" expected-type="javax.sql.DataSource"/> 

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> 


</beans> 

Я добавил <property name="jtaTransactionManager" ref="transactionManager"/> под sessionFactory боба definition.After это я могу использовать

session = sessionFactory.getCurrentSession(); в моем классе дао слоя.