0

私のプロジェクトでは EJB と JPA (Hibernate を使用) を使用していましたが、Spring に切り替える必要がありました。その前はすべてうまくいっていました。EntityManager の注入、トランザクションの制御などに使用される EJB。

OK、Spring に切り替えたとき、Spring を初めて使用したため、多くの問題が発生しました。しかし、すべてが実行された後、問題があります。データがデータベースに保存されることはありません。トランザクションを制御するようにSpringを構成しました。JSFで使用されるSpring Beanがあり、それには大変な作業を行うSpringサービスがあります。このサービスには EntityManager が注入され、@Transactional REQUIRED を使用します。このサービスは、entityManager.persist(bean) を呼び出す DAO に EntityManager を渡します。

選択はうまく機能しているように見え、JTA トランザクションはうまく機能しているように見えますが (ログで見ました)、エンティティは保存されません!

ログは次のとおりです。

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter: doFilterInternal() (linha 136): Opening JPA EntityManager in OpenEntityManagerInViewFilter

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory: doGetBean() (linha 245): Returning cached instance of singleton bean 'transactionManager'

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: getTransaction() (linha 365): Creating new transaction with name [br.org.cni.pronatec.controller.service.MontanteServiceImpl.adicionarValor]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doBegin() (linha 493): Opened new Session [org.hibernate.impl.SessionImpl@2b2fe2f0] for Hibernate transaction

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doBegin() (linha 504): Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@2b2fe2f0]

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doBegin() (linha 569): Exposing Hibernate transaction as JDBC transaction [com.sun.gjc.spi.jdbc40.ConnectionHolder40@3bcd4840]

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler: doJoinTransaction() (linha 383): Joined JTA transaction


INFO: Hibernate: 
    select
        hibernate_sequence.nextval 
    from
        dual

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: processCommit() (linha 752): Initiating transaction commit

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doCommit() (linha 652): Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@2b2fe2f0]

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doCleanupAfterCompletion() (linha 734): Closing Hibernate Session [org.hibernate.impl.SessionImpl@2b2fe2f0] after transaction

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.SessionFactoryUtils: closeSession() (linha 800): Closing Hibernate Session

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter: doFilterInternal() (linha 154): Closing JPA EntityManager in OpenEntityManagerInViewFilter

INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.jpa.EntityManagerFactoryUtils: closeEntityManager() (linha 343): Closing JPA EntityManager

ログにはトランザクションのコミットが表示されますが、挿入クエリは表示されません (Hibernate はクエリを出力しています)。また、シーケンス ID の次の値を取得するための Hibernate ルックアップも表示されます。しかし、その後、実際に挿入されることはありません。

春のコンテキスト構成は次のとおりです。

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="PronatecPU" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
<property name="jpaProperties">
    <props>
    <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
    </props>
</property>
</bean>


<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
    <property name="transactionManagerName" value="java:/TransactionManager" />
<property name="userTransactionName" value="UserTransaction" />
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />


<tx:annotation-driven transaction-manager="transactionManager" />

ここに私のpersistence.xmlがあります:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" 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">
  <persistence-unit name="PronatecPU" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/pronatec</jta-data-source>
    <class>br.org.cni.pronatec.model.bean.AgendamentoBuscaSistec</class>
    <class>br.org.cni.pronatec.model.bean.AgendamentoExportacaoZeus</class>
    <class>br.org.cni.pronatec.model.bean.AgendamentoImportacaoZeus</class>
    <class>br.org.cni.pronatec.model.bean.Aluno</class>
    <class>br.org.cni.pronatec.model.bean.Curso</class>
    <class>br.org.cni.pronatec.model.bean.DepartamentoRegional</class>
    <class>br.org.cni.pronatec.model.bean.Dof</class>
    <class>br.org.cni.pronatec.model.bean.Escola</class>
    <class>br.org.cni.pronatec.model.bean.Inconsistencia</class>
    <class>br.org.cni.pronatec.model.bean.Matricula</class>
    <class>br.org.cni.pronatec.model.bean.Montante</class>
    <class>br.org.cni.pronatec.model.bean.ParametrosVingentes</class>
    <class>br.org.cni.pronatec.model.bean.TipoCurso</class>
    <class>br.org.cni.pronatec.model.bean.Turma</class>
    <class>br.org.cni.pronatec.model.bean.UnidadeFederativa</class>
    <class>br.org.cni.pronatec.model.bean.ValorAssistenciaEstudantil</class>
    <class>br.org.cni.pronatec.model.bean.ValorHora</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <property name="current_session_context_class" value="thread"/>
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>
      <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
      <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup"/>
      <property name="hibernate.hbm2ddl.auto" value="update"/>
    </properties>
  </persistence-unit>
</persistence>

マネージド Bean に挿入される私のサービスは次のとおりです。

@Service
@Scope("prototype")
@Transactional(propagation= Propagation.REQUIRED)
public class MontanteServiceImpl {
    // more code
    @PersistenceContext(unitName="PronatecPU", type= PersistenceContextType.EXTENDED)
    private EntityManager entityManager;
    // more code
    // The method that is called by another public method that do something before
    private void salvarMontante(Montante montante) {
        montante.setDataTransacao(new Date());

        MontanteDao montanteDao = new MontanteDao(entityManager);
        montanteDao.salvar(montante);
    }
    // more code
}

私の MontanteDao は、次のようにベース DAO から継承します。

public class MontanteDao extends BaseDao<Montante> {

    public MontanteDao(EntityManager entityManager) {
        super(entityManager);
    }

}

BaseDao で呼び出されるメソッドは次のとおりです。

public void salvar(T bean) {
    entityManager.persist(bean);
}

ご覧のとおり、挿入された entityManager を選択して persist() メソッドを呼び出すだけです。トランザクションはSpringによって制御されており、ログに出力されますが、挿入クエリはログに出力されず、保存されません。

私の悪い英語について申し訳ありません。誰が助けてくれてありがとう。

編集: デバッグ、各 entityManager.persist(T) の後に、「挿入」タイプの actionQueue に別のアクションがキューに入れられていることがわかりました。結局のところ、アクションをキューに入れるだけで、実行することはありません。誰かがすでにこの種の問題に直面していますか?

4

2 に答える 2

0

さて、ようやく問題を解決しました。JTAの設定に誤りがありました。何ができるかわかりませんが、RESOURCE_LOCALに変更して機能しました。

初めてRESOURCE_LOCALを試したとき、Glassfishが@PersistenceContextアノテーションを検証し、「persistence-context-ref-name[...]に対応する永続性ユニットを解決できませんでした」をスローする問題が発生しました。次に、この検証を無効にする良い方法を見つけました。

metadata-complete=true

私のweb.xmlで。「注釈は必要ないので見ないでください」と書かれています。さて、Springは私のコンテナであり、それ自体でアノテーションを調べ、必要なものを構成します。そうすれば、サーバーは必要ありません。

結局のところ、私の構成は次のようになります。

web.xml:

<web-app version="3.0"
     xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      metadata-complete="true">

Springのcontext.xml:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="PronatecPU" />
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
    <property name="loadTimeWeaver">
        <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
    </property>
    </bean>

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

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <tx:annotation-driven />

persistence.xml:

<persistence-unit name="PronatecPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <non-jta-data-source>jdbc/pronatec</non-jta-data-source>
    <!-- ... -->

そして、注入されたentityManager:

@PersistenceContext(type= PersistenceContextType.EXTENDED)
private EntityManager entityManager;

これが同じ問題を抱えている人に役立つことを願っています。

于 2012-04-10T13:55:06.687 に答える
0

データベースへのフラッシュを強制してみてください。

entityManager.flush();
于 2012-04-05T16:16:49.250 に答える