16 Stimmen

TransactionRequiredException: Ausführen einer Abfrage zum Aktualisieren/Löschen

Es fällt mir schwer, eine Lösung für mein Problem zu finden.
Ich habe eine Serviceklasse, die eine Methode zum Setzen eines Verifizierungsflags bei der Anmeldung enthält.

@Service("userRolesService")
@Repository
@Transactional
public class UserRolesService {
   public void verify() {
       repository.verifyUser();
   }
}

Mein Repository ist ein SpringData CrudRepository, und verifyUser ist etwas wie

 @Modifying
 @Query("UPDATE user SET (verified = 1 WHERE verified=0)")
 public void verifyUser();

Wenn der Code direkt in einem Unit-Test aufgerufen wird, funktioniert alles einwandfrei. Wenn ich ihn von meinem Authentifizierungsanbieter über die Anwendung aufrufe, erhalte ich die folgende Ausnahme:

javax.persistence.TransactionRequiredException : Ausführen einer Abfrage zum Aktualisieren/Löschen

Die Dienstklasse wird sowohl in meinen Unit Test als auch in den Authentifizierungsanbieter injiziert, indem die @Autowired Bemerkung. Der Test selbst weist keine interessanten Anmerkungen auf, ebenso wenig wie der Authentifizierungsanbieter.

Mir gehen gerade die Ideen aus, wenn also jemand einen Tipp hat, wäre ich sehr dankbar.

EDIT: Anstatt das Update-Skript verifyUser aufzurufen, rufe ich jetzt alle nicht verifizierten Benutzer ab, setze das Flag verifiziert und verwende die save()-Methode des Repositorys. Das funktioniert, ist aber sehr hässlich, also bin ich offen für bessere Vorschläge.

EDIT2:

Pro Anfrage hier ist die Persistenz Teil der Konfiguration, ich denke, das ist am wichtigsten, der Rest befasst sich nur mit der Authentifizierung. Diese Konfiguration wird sowohl in den Unit-Tests als auch in der Web-App verwendet. Der einzige Unterschied ist, dass die Datenquellen H2 DB für die Unit-Tests und mysql für die Web-App eingebettet sind.

<beans [..]>

    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
          depends-on="persistenceInitializer">
        <property name="dataSource" ref="dataSource"/>
        <property name="persistenceUnitName" value="jpa"/>
        <property name="packagesToScan">
            <list>
                <value>com.example.model</value>
            </list>
        </property>
        <property name="jpaVendorAdapter">
            <bean class="com.example.persistence.adapter.ConfigurationRetainingHibernateJpaVendorAdapter">
                <property name="database" value="${spring.hibernate.database}"/>
                <property name="generateDdl" value="${spring.hibernate.generateDdl}"/>
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.DefaultComponentSafeNamingStrategy
                </prop>
            </props>
        </property>
    </bean>

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

    <jpa:repositories base-package="com.example.persistence.repository"/>

    <tx:annotation-driven/>

    <bean id="persistenceInitializer" class="com.example.persistence.init.NoOpInitializer"/>

</beans>

Zusätzlich habe ich eine Konfiguration, die nur in der Web-App, nicht die Unit-Tests ist:

<beans [..]>

    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:application.properties</value>
            </list>
        </property>
    </bean>

    <mvc:annotation-driven/>

    <mvc:default-servlet-handler/>

    <context:annotation-config/>

</beans>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X