2011-12-30 4 views
0

J'ai créé une application de ressort simple pour tester les bases de la transaction déclarative de printemps. Conformément aux règles, la transaction déclarative doit être annulée dans le cas de RuntimeException. Mais ça ne se retournait pas dans mon cas.Printemps Déclaration Transaction non annulée

classe de test principal a le code

public class SpringOraTest { 
public static void main(String[] args) { 
    ApplicationContext aplctx= new  
FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml"); 

    //Call to test Declarative Transaction with Annotation 
TrxHandleAnnotated prxyobj=((TrxHandleAnnotated)aplctx.getBean("dbCommandAnnotated")); 
prxyobj.doTask(); 
} 
} 

La classe TrxHandleAnnotated avait code: -

@Transactional 
public class TrxHandleAnnotated 
public void doTask(){ 
ApplicationContext aplctx= new 
FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml"); 
JdbcTemplate jdbcTemplate= (JdbcTemplate)aplctx.getBean("jdbcTemplate"); 

jdbcTemplate.update("insert into kau_emp values(4,'forthmulga')"); 

throw new RuntimeException(); 
} 

Et il a été nécessaire dans la configuration XML de configuration.

Je m'attendais à ce que cette transaction soit annulée lorsque l'exception est levée. Mais il n'a pas été annulé et l'enregistrement a été engagé pour DB.

Même après une longue recherche sur internet, je ne pouvais pas comprendre pourquoi il n'était pas annulé. Plus tard, j'ai réalisé que, dans le code doTask(), je crée à nouveau le contexte et prend notre instance de JdbcTemplate en dehors du nouveau contexte. C'était la cause profonde du problème.

J'ai modifié le code de manière à ce que les deux classes utilisent un certain contexte. Et ça a marché !!!

public class SpringOraTest { 
public static ApplicationContext aplctx; 
public static void main(String[] args) { 
    aplctx= new FileSystemXmlApplicationContext("src\\config\\SpringConfigForOra.xml"); 

    //Call to test Declarative Transaction with Annotation 
    TrxHandleAnnotated prxyobj=  
((TrxHandleAnnotated)aplctx.getBean("dbCommandAnnotated")); 
prxyobj.doTask(); 
} 

@Transactional 
public class TrxHandleAnnotated 
public void doTask(){ 

JdbcTemplate jdbcTemplate=(JdbcTemplate)SpringOraTest.aplctx.getBean("jdbcTemplate"); 
jdbcTemplate.update("insert into kau_emp values(4,'forthmulga')"); 

throw new RuntimeException(); 
} 

Ceci est une leçon apprise pour moi que, sauf exigence contraire, l'application entière doit utiliser un seul objet contexte. Cela semblera trop évident Les pratiquants du printemps, mais les novices du printemps comme moi peuvent commettre de telles erreurs idiotes. Alors pensé à le partager.

Dans ce cas particulier, au lieu de créer manuellement JdbcTemplate, il vaut mieux le déclarer en tant que variable membre et utiliser l'injection Setter.

+0

Vous devriez ouvrir un blog pour partager vos découvertes. StackOverflow est destiné à poser des questions. –

Répondre

-1

utilisez @TransactionConfiguration("name",ROLLBACK); //check syntax après @Transactional en déclarant TrxHandleAnnotated. Voir this link pour plus d'informations sur @Transcational et son utilisation.

Questions connexes