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.

C'est difficile de ce faire vous gâcher la CMT et GSM dans le même lieu.

OriginalL'auteur fracz | 2013-08-15