Comment exécuter une requête SQL personnalisée avec le printemps géré transactionnelle EntityManager
J'ai une application construite sur de Printemps. Je laisse le Printemps de faire tout @Transactional
de la magie et tout fonctionne bien aussi longtemps que je utiliser sur mon entités qui sont mappés à des objets Java.
Cependant, lorsque je veux faire un travail personnalisé sur une table qui n'est pas mappé à un de mes Java entités, je suis coincé. Il y a quelques temps, j'ai trouvé une solution pour exécuter une requête personnalisée comme ceci:
//em is instance of EntityManager
em.getTransaction().begin();
Statement st = em.unwrap(Connection.class).createStatement();
ResultSet rs = st.executeQuery("SELECT custom FROM my_data");
em.getTransaction().commit();
Quand j'ai essayer avec le gestionnaire de l'entité injecté à partir du Printemps avec la @PersistenceContext
annotation, je reçois presque évident exception:
java.lang.IllegalStateException:
Not allowed to create transaction on shared EntityManager -
use Spring transactions or EJB CMT instead
J'ai enfin réussi à extraire non partagé Gestionnaire d'Entité comme ceci:
@Inject
public void myCustomSqlExecutor(EntityManagerFactory emf){
EntityManager em = emf.createEntityManager();
//the em.unwrap(...) stuff from above works fine here
}
Néanmoins, je trouve cette solution ni à l'aise ni élégant. Je me demande juste si il y a un autre moyen d'exécuter des requêtes SQL personnalisées en ce Printemps transactionnelles axée sur l'environnement?
Pour ceux qui sont curieux de ce problème est apparu quand j'ai essayé de créer des comptes d'utilisateur de mon application et dans le forum à la fois - je ne voulais pas les utilisateurs du forum de la table pour être mappé à un de mes Java entités.
OriginalL'auteur fracz | 2013-08-15
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser createNativeQuery d'exécuter des requêtes SQL sur votre base de données.
La réponse ci-dessus est toujours valable, mais je voudrais modifier en quelques renseignements supplémentaires qui peuvent également être utiles aux gens de regarder cette question.
S'il est vrai que vous pouvez utiliser le createNativeQuery méthode à exécuter natif de requêtes à l'aide d'un EntityManager; il existe une alternative (sans doute le meilleur) moyen de le faire si vous utilisez le Framework Spring.
La méthode alternative pour l'exécution de requêtes avec le Printemps (qui fonctionne avec la configuration de transactions) est d'utiliser la JDBCTemplate. Il est possible d'utiliser les deux JDBCTemplate et un EntityManager dans la même application. La configuration devrait ressembler à quelque chose comme ceci:
InfrastructureConfig.class:
AppConfig.class:
Et un exemple de référentiel qui permettrait d'utiliser à la fois JPA et JDBC:
createQuery()
méthode, mais avec la même exception, comme ci-dessus.createNativeQuery()
résout le problème, merci beaucoup!OriginalL'auteur FGreg
Vous pouvez utiliser L'EntityManager.createNativeQuery(String sql) d'utiliser directement le code sql ou de l'utilisation L'EntityManager.createNamedQuery(String nom) pour exécuter des requêtes précompilées.
Vous utilisez toujours le printemps géré par l'Entité gestionnaire, mais le travail sur la non gestion des objets
OriginalL'auteur Luca Basso Ricci