4

open-session-in-view 動作を既存の純粋な JPA アプリケーションに追加しようとしています。サービス層で Spring を使用することはオプションではありません。ビューを Spring の OpenEntityManagerInViewFilter でラップしたいので、EJB レイヤーを変更する必要はありません。

OpenEntityManagerInViewFilter (Spring 3.2.2) を JBoss 6.1 で動作させることができません。フィルターは確実に呼び出されていますが、ビューでまだ​​ LazyInitializationException が発生しています。

フィルターとセッション Bean は、EntityManager の異なるインスタンス (およびクラス) を使用しています。フィルターは を取得していますがorg.hibernate.ejb.EntityManagerImpl、セッション Bean は を取得していorg.jboss.jpa.tx.TransactionScopedEntityManagerます。どのSpring構成がこれに責任があるのか​​ わかりません。

関連するコード/構成は次のとおりです。

戦争/WEB-INF/classes/test.web.servlet.TestServlet

public class TestServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

@EJB
private ServiceLocal service;

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

    long parentId = Long.parseLong(req.getParameter("parentId"));
    Parent parent = service.retrieveParent(parentId);

    // this call throws a LazyInitializationException
    // because parent.children.session is NULL
    parent.getChildren().iterator().next().getName();

    req.setAttribute("parent", parent);
    RequestDispatcher requestDispatcher = this.getServletContext().getRequestDispatcher("/WEB-INF/jsp/view.jsp");
    requestDispatcher.forward(req, resp);
}
}

ejb/test.ejb.session.ServiceBean

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class ServiceBean implements ServiceLocal, Service {

    @PersistenceContext(name="test")
    private EntityManager entityManager;

    @Override
    public Parent retrieveParent(Long parentId) {
        return entityManager.find(Parent.class, parentId);
    }
}

戦争/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">

<display-name>test-war</display-name>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring.xml</param-value>
</context-param>

<filter>
    <filter-name>osiv-filter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    <init-param>
        <param-name>flushMode</param-name>
        <param-value>AUTO</param-value>
    </init-param>
</filter>

<servlet>
    <servlet-name>test-servlet</servlet-name>
    <servlet-class>test.web.servlet.TestServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>test-servlet</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

<filter-mapping>
    <filter-name>osiv-filter</filter-name>
    <servlet-name>test-servlet</servlet-name>
</filter-mapping>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

</web-app>

戦争/WEB-INF/spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="persistenceUnitName" value="test" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.transaction.manager_lookup_class">
                org.hibernate.transaction.JBossTransactionManagerLookup
            </prop>
        </props>
    </property>
</bean>
</beans>

ejb/META-INF/persistence.xml

<persistence
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">   
   <persistence-unit name="test" transaction-type="JTA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/MSSQLDS</jta-data-source>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
         <property name="hibernate.show_sql" value="false" />
         <property name="hibernate.format_sql" value="true" />
         <property name="hibernate.use_sql_comments" value="true" />
         <property name="jboss.entity.manager.factory.jndi.name" value="java:/testEntityManagerFactory" />
         <property name="jboss.entity.manager.jndi.name" value="java:/testEntityManager" />
      </properties>
   </persistence-unit>
</persistence>
4

4 に答える 4

2

カスタム EntityManagerFactory を使用して JDNI 経由で EntityManagerFactory をルックアップする必要はないと思います。要素がそれを処理する必要があります。

私はあなたのセットアップをもう少し考えましたが、春の OpenEntityManagerInViewFilter がうまくいくとは思いません。エンティティ マネージャーを現在のスレッドにバインドして、Spring のトランザクション管理コードがそれを再利用できるようにします。問題は、Spring がサービス Bean のトランザクション管理を処理しないことです。これは、アプリケーション サーバーによって処理されるためです。アプリケーション サーバーは、Spring によってスレッドにバインドされたエンティティ マネージャーを検出せず、別のエンティティ マネージャーを作成します。その結果、2 つの異なるインスタンスが生成されます。

それを機能させるには、Spring でサービス Bean を定義して、Spring がトランザクション管理を処理するか、jboss seam を使用する必要があります ( JBoss Seam: How to Open jpa/hibernate session in view )

于 2013-05-10T17:48:24.023 に答える
1

私は spring/jboss のセットアップに慣れていないため、いくつか見逃していました。

あなたのサービス Bean は、Spring ではなく JBoss サーバーによって管理されていると思います。LocalContainerEntityManagerFactoryBean を定義することにより、Spring で実際に EntityManagerFactory を構成します (アプリケーション サーバーによって管理されるものと非常によく似ています)。アプリケーション サーバーによって管理されるエンティティ マネージャーによって注入されるはずだったビュー フィルターでのオープン セッションには、Spring によって管理される EntityManager が注入されます。

次のスプリング構成で問題が解決すると思います( jndi-name 属性を調整することを忘れないでください)

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:jee="http://www.springframework.org/schema/jee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   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.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<context:annotation-config/>
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence-units/test"/>
<tx:jta-transaction-manager/>

于 2013-05-09T22:32:11.403 に答える