TransactionRequiredException: aucune transaction n'est en cours avec Spring Data JPA
Je regardé autour de pour des problèmes similaires, mais ne pouvait pas trouver un solution pour cela:
J'ai un Spring Data JPA application qui à chaque fois que j'essaie de faire une trasaction-je obtenir javax.persistence.TransactionRequiredException: no transaction is in progress
.
Je crois qu'il a quelque chose à faire avec le Gestionnaire de Transactions ou de l'Entité Gestionnaire de l'Usine, mais ne peux pas mettre mon doigt sur elle.
Le contexte fichiers sont ici (dernière archivés sont ici), mais ici, c'est la partie de la matière:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceMySQL" />
<property name="persistenceUnitName" value="spring-jpa" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="showSql" value="true" />
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSourceMySQL"/>
</bean>
<bean id="dataSourceMySQL" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/dbname"/>
<property name="username" value="user"/>
<property name="password" value="pass"/>
</bean>
<jpa:repositories base-package="com.simplecash.dal.repository" />
Un exemple de Référentiel est ici puis création d'un Référentiel d'Usine ici, dont je ne suis pas sûr si j'ai besoin...
Ensuite l'utiliser ici (ligne 34).
public void populateWithTestData() {
Bank bank = new Bank();
bank.setName("ContentName");
bank.setCode("ContentCode");
RepositoryFactory.getEntityManager().getTransaction().begin();
BankRepository bankRepository = RepositoryFactory.getRepository(BankRepository.class);
bankRepository.save(bank);
bankRepository.flush();
RepositoryFactory.getEntityManager().getTransaction().commit();
}
Un couple de choses sont fausses ci-dessus, mais je j'ai essayé de fixation et ne peut pas:
- Lancer et valider les transactions sont explicites.
bankRepository
devrait être@Autowired
, mais lorsque je fais cela, je reçoisnull
. Cependant, dans ce cas de test il est Autocâblés et les œuvres.
Quelqu'un a été confronté à un problème similaire et qui sait ce qui se passe?
Merci une tonne de prendre le temps de lire ceci. Espérons que la réponse à cette question permettra d'aider d'autres gens.
Vous devez vous connecter pour publier un commentaire.
À la fois réponse ici offrent de bons points (à l'aide d'injection pour obtenir le proxy de haricots et de l'aide de la transaction-les annotations), cependant, je suis assez sûr que pour l'annotation-driven opérations de travaux (@Transactionnelle), vous devez ajouter les lignes suivantes à votre xml de configuration:
Aussi assurez-vous d'ajouter le tx-espace de noms dans votre haricots-tag:
Ce Printemps avec votre référentiel de haricots ( par exemple
BankRepository
), il crée un proxy autour d'elle, puis il est prêt à être injecté dans d'autres collaborateurs, qui dans votre cas estDatabaseManagerDAO
. Toutefois, si vous créez l'objet vous-même comme vous le faites:Au lieu d'attendre le Printemps proxy ( qui en fait déjà la gestion des transactions pour vous ), vous obtenez un simple objet qui n'est pas conscient de ce qui l'au-delà, il est immédiat de la déclaration.
Ce que vous devez faire est plutôt de confiance Printemps à faire de la plomberie pour vous et juste injecter un
bankRepository
fève dans unDatabaseManagerDAO
(bien que je ne pense pas vraiment que vous avez besoin de DAO et de Dépôt, étant donné que ces termes signifient vraiment la même chose 🙂Pas besoin d'une autre abstraction. Juste injecter comme un haricot pour composant qui a besoin d'elle.
bankRepository
devrait être@Autowired
, mais lorsque je fais cela, je reçoisnull
. Cependant, dans ce cas de test il est Autocâblés et les œuvres.Dans un cas où il fonctionne vous exécutez vos tests avec
AbstractTransactionalJUnit4SpringContextTests
, qui sait sur 'bankRepository' haricot, d'où autowires il. Dans votreDatabaseManagerDAO
, je ne vois ni permettra à l'autowiring ni une définition pour labankRepository
, en fait, vous créez manuellement à partir de l'usine.MODIFIER pour répondre à des commentaires
Ce
jpa:repositories
dans votre configuration XML vraiment n' => il scanne le paquet et crée des beans Spring pour chaque composant qui est annoté comme@Repository
ou met en œuvre uneRepository
interface.Avec cela à l'esprit, ce que vous devez faire pour utiliser un
BankRepository
référentiel dans votreDatabaseManagerDAO
est de l'injecter. Vous pouvez le faire via "permettra à l'autowiring":plutôt que de créer manuellement c'creux de votre usine.
De nouveau,
DatabaseManagerDAO
dans votre cas est probablement un service (@Service
), et pas unDAO
, mais je vais laisser à vous de décider sur qui.Avis qu'un
DatabaseManagerDAO
devrait également être chargé par Ressort pour l'permettra à l'autowiring de travailler, alors assurez-vous qu'il dispose de l'un des Printemps les annotations (@Service
/@Component
) lorsque vous créez un package d'analyse ( par exemple,<context:component-scan base-package="org.example"/>
).BankRepository
?J'ai eu un problème similaire lors de la combinaison de
spring-batch
etspring-jpa
. Dans mon lot XML, j'ai eu cette ligne:qui a provoqué une erreur depuis JPA a besoin d'un
PlatformTransactionManager
.Je pense que dans votre installation, les Transactions sont gérées par JTA, de sorte que vous ne pouvez pas explicitement démarrer/arrêter (c'est à dire em.getTransaction().begin() ne fonctionnera pas). Essayez de parler de Printemps que vous voulez une certaine méthode pour faire partie d'un JTA (réussi) de la transaction via l'annotation , comme:
@Transactional
annotation, mais n'a pas fonctionné. Le code que j'ai maintenant (avec explicite commencer et valider) fonctionne, mais je pense que le référentiel desave
a déjà le@Transactional
attribut et je n'ai pas forcément besoin d'elle dans ma fonction (bien que je suppose que je peux l'ajouter). Je pense que le problème se situe soit dans la façon dont j'ai injecter leEntityManagerFactory
bean ou il y a quelque chose qui manque dans le contexte de l'application le fichier xml..