Sie sind auf Seite 1von 13

Transacciones con Spring Framework y EJB 3.

0
Publicado:Martes,10Febrero200903:00

Elprocesamientodetransaccionesdeberalograrunaltogradodeintegridadyconsistenciadedatos.En
esteartculoveremosalgunoserrorescomunesalusartransaccionesenJava.UsaremosejemplosconSpring
FrameworkyEnterpriseJavaBeans(EJB)3.0parademostrarelusodeunaestrategiatransaccionalefectiva.

El porqu de las transacciones


Elusomscomndelastransaccionesdentrodeunaaplicacinesparamantenerunaltogradodeintegridadyconssitenciaenlos
datos.Sinonosimportalacalidaddenuestrosdatos,notenemosquepreocuparnosenusartransacciones.Despusdetodo,el
soportedetransaccionesenlaplataformaJavapuedeafectarelrendimiento,introducirproblemasdeconcurrenciaenlabasede
datos,yaumentarlacomplejidaddelaaplicacin.
Peroaquellosquedesarrolladoresquenosepreocupanporlastransaccioneslohacenbajosupropioriesgo.Casitodaslas
aplicacionesdenegociorequierenunaltoniveldecalidaddedatos.Sololaindustriafinancieradeinversionesgastadecenasde
billonesdedlaresennegociosfallidos,ylosdatosincorrectospormalastransaccionessonlasegundacausa.Aunquelafaltade
soportetransaccionalesslounodelosfactoresquellevanadatosincorrectos(aunqueunodelosfactoresmsimportantes),se
puedeinferirquebillonesdedlaressegastanenlaindustriafinancieracomoresultadodeunpobresoportetransaccional.
Otrafuentedeproblemaseseldesconocimientosobreelsoportedetransacciones.Muyamenudoescuchofrasescomo"no
necesitamostransaccionesennuestraaplicacinporquenuncafalla".Si,claro.Fuitestigodeaplicacionesque,dehecho,casinunca
lanzabanexcepciones.Estasaplicacionesteniancdigobienescrito,rutinasdevalidacinbienescritas,pruebascompletasy
coberturadecdigoparaevitarelcostoenrendimientoylacomplejidadasociadaalprocesamientodetransacciones.Elproblemacon
estaformadepensaresqueslotieneencuentaunadelascaractersticasdelsoportetransaccional:laatomicidad.Laatomicidad
aseguraquetodaslasactualizacionessontratadascomounanicaunidad,ysontodasconfirmadas(commit)odeshechas(rollback).
Peroelsoportetransaccionalesmsquehacerunrollbackocoordinaractualizaciones.Otroaspecto,elaislamiento,aseguraque
unaunidaddetrabajoestaisladadelrestodelasunidadesdetrabajo.Sinunaislamientotransaccionaladecuado,otrasunidadesde
trabajopuedenaccederaactualizacionesqueestnsiendorealizadasdporunaunidaddetrabajoencurso,aunqueelprocesode
estaunidaddetrabajoestincompleto.Comoresultado,sepodrantomardecisionesdenegocioenbaseadatosparciales,loque
podraresultadoenoperacionesfallidasuotrosresultadosnegativos(ocostosos).
Entonces,dadoelaltocostoyelimpactonegativodelosdatosincorrectos,yconelconocimientobsicoparacomprenderquelas
transaccionessonimportantes(ynecesarias),necesitamosutilizarlastransaccionesyaprendercmosaltearlosproblemasque
puedensurgir.Entoncesavanzamosyagregamostransaccionesanuestrasaplicaciones.Yaquesdondeempiezanlosproblemas.
LastransaccionesnosiempreparecenfuncionarcomoseesperaenlaplataformaJava.Acontinuacinveremosporquocurreesto,

LastransaccionesnosiempreparecenfuncionarcomoseesperaenlaplataformaJava.Acontinuacinveremosporquocurreesto,
conejemplosdecdigoyerrorescomunesquesecomentenenlamayoradelosentornosproductivos.
ParalosejemplosdecdigovamosausarSpringFramework(versin2.5),perolosconceptosdetransaccionessonlosmismospara
laespecificacinEJB3.0.Enlamayoradeloscasos,esslocuestindereemplazarlaanotacindeSpringFramework
@Transactional conlaanotacindeEJB3.0 @TransactionAttribute .Enloscasosesquehayadiferenciasentreestosframeworks,

vamosaincluirejemplosparaambos.

Problemas comunes en transacciones locales


Unbuenpuntodeinicioesconelescenariomssimple:elusodetransaccioneslocales,tambinconocidascomotransaccionesde
basededatos.Enlosprimerosdasdelapersistenciaenlasbasesdedatos(porejemplo,conJDBC),sesoladelegarel
procesamientodelastransaccionesalabasededatos.Despusdetodo,noesloquelasbasesdedatoshacen?Las
transaccioneslocalestrabajanbienparaUnidadesLgicasdeTrabajo(ULT,oLUWeningls)queejecutanunanicasentencia
insert,updateodelete.Porejemplo,acontinuacinvemoscdigousandoJDBCquerealizauninsertdeunaordendecompraala
tabla TRADE :

@Stateless
publicclassTradingServiceImplimplementsTradingService{
@ResourceSessionContextctx;
@Resource(mappedName="java:jdbc/tradingDS")DataSourceds;

publiclonginsertTrade(TradeDatatrade)throwsException{
ConnectiondbConnection=ds.getConnection();
try{
Statementsql=dbConnection.createStatement();
Stringstmt=
"INSERTINTOTRADE(ACCT_ID,SIDE,SYMBOL,SHARES,PRICE,STATE)"
+"VALUES('"
+trade.getAcct()+"','"
+trade.getAction()+"','"
+trade.getSymbol()+"',"
+trade.getShares()+","
+trade.getPrice()+",'"
+trade.getState()+"')";
sql.executeUpdate(stmt,Statement.RETURN_GENERATED_KEYS);
ResultSetrs=sql.getGeneratedKeys();
if(rs.next()){
returnrs.getBigDecimal(1).longValue();

}else{
thrownewException("TradeOrderInsertFailed");
}
}finally{
if(dbConnection!=null)dbConnection.close();
}
}
}

EstecdigoJDBCnoincluyeningunalgicadetransaccin,ypersisteunaordendecompradeaccionesenlatabla TRADE dela


basededatos.Enestecaso,labasededatosseencargademanejarlalgicatransaccional.
EstofuncionabienparaunanicaaccinsobrelabasededatosdentrodeestaULT.Perosupongamosquenecesitamosactualizarel
balancedelacuentaenelmismomomentoqueinsertamoslaordendecompraenlabasededatos.Porejemplo:

publicTradeDataplaceTrade(TradeDatatrade)throwsException{
try{
insertTrade(trade);
updateAcct(trade);
returntrade;
}catch(Exceptionup){
//logdelerror
throwup;
}
}

Enestecaso,losmtodos insertTrade() y updateAcct() usancdigoestndarJDBCsintransacciones.Unavezqueelmtodo


insertTrade() finaliza,labasededatospersiste(yhacecommit)alaordendecompra.Sielmtodo updateAcct() fallapor

cualquierrazn,laordendecompraseguirenlatabla TRADE alfinalizarelmtodo placeTrade() ,resultandoendatos


inconsistentesenlabasededatos.Sielmtodo placeTrade() hubierausadotransacciones,ambasactividadessehubieranincluido
enlamismaULT,ysehubierarealizadounrollbackdelaordendecomprasilaactualizacindelacuentafallaba.
ConlapopularidaddelosframeworksdepersistenciaJavacomoHibernate,TopLinkyJavaPersistenceAPI(JPA),esbastanteraro
escribircdigoJDBCdirectamente.Generalmenteusamoslosframeworksdemapeoobjetorelacional(ORM)parahacernoslavida
msfacilyreemplazartodoelcdigoJDBCmolestoporunassimplesinvocaciones.Porejemplo,parainsertarunaordendecompra
delejemploanteriorenJDBC,usandoSpringFrameworkconJPA,mapeamoselobjeto TradeData alatabla TRADE yreemplazamos
todoelcdigoJDBCconelcdigoJPA:

publicclassTradingServiceImpl{

publicclassTradingServiceImpl{
@PersistenceContext(unitName="trading")EntityManagerem;

publiclonginsertTrade(TradeDatatrade)throwsException{
em.persist(trade);
returntrade.getTradeId();
}
}

Notemosqueenesteejemploinvocamosalmtodo persist() del EntityManager parainsertarunaordendecompra.Simple,no?.


Notanto.Estecdigonovaainsertarlaordendecompraenlatabla TRADE comoesperaramos,nitampocolanzaunaexcepcin.
Simplementevaaretornarelvalor0comolaclavedelaordendecomprasincambiarlabasededatos.Esteesunodelosprimeros
erroresalprocesartransacciones:losframeworksORMnecesitandetransaccionesparadispararlasincronizacinentreel
cachdeobjetosylabasededatos.EsatravsdelcommitdelatransaccinqueelcdigoSQLsegenerayseafectaalabase
dedatosconlaaccin(esdecir,conelinsert,update,delete).SinlatransaccinnohayundisparadoralORMparaquegenereel
cdigoSQLypersistaloscambios,yaselmtodoterminasinexcepciones,sinactualizaciones.SiseusaunframeworkORM,
debemosusartransacciones.Yanopodemosconfiarenquelabasededatosvaamanejarlasconexionesyhacerelcommitdel
trabajo.
Estosejemplossimplesdeberanbastarparadejarenclaroquelastransaccionessonnecesariasparamantenerintegridady
consistenciadedatos.Peroapenassoneliniciodelacomplejidadylosproblemasasociadosconlaimplementacindetransacciones
enJava.

Problemas comunes con la anotacin

@Transactional

de Spring Framework

Entonces,probamoselcdigoanteriorydescubrimosqueelmtodo persist() nofuncionasintransacciones.Buscamosen


Internet,investigamosalgunoslinksynosencontramosconqueSpringFrameworktieneunaanotacin @Transactional .Asquela
agregamosanuestrocdigo,comovemosacontinuacin:

publicclassTradingServiceImpl{
@PersistenceContext(unitName="trading")EntityManagerem;

@Transactional
publiclonginsertTrade(TradeDatatrade)throwsException{
em.persist(trade);
returntrade.getTradeId();
}
}

Volvemosaprobarelcdigo,ysiguesinfuncionar.ElproblemaesquehayquedecirleaSpringqueestamosuandoanotacionespara
gestionarlastransacciones.Amenosqueestemoshaciendounapruebaunitariacompleta,esteerrorsueleserdificildedescubrir,y
hacequelosdesarrolladoresterminenaadiendolalgicadetransaccionesenlosarchivosdeconfiguracindeSpringenvezde
usaranotaciones.
Cuandoseusalaanotacin @Transactional deSpring,debemosagregarlalneasiguienteanuestroarchivodeconfiguracinde
Spring:

<tx:annotationdriventransactionmanager="transactionManager"/>

Lapropiedad transactionmanager tieneunareferenciaalbeanquegestionalastransacciones,definidoenelarchivode


configuracindeSpring.EstecdigolediceaSpringqueuselaanotacin @Transactional cuandoapliqueelinterceptorde
transacciones.Sinestalnea,seignoralaanotacin @Transactional ,yenconsecuencianoseusantransaccionesenelcdigo.
Esteeselusobsicodelaanotacin @Transactional ,yessloelcomienzo.Enelejemplousamoslaanotacin @Transaction sin
especificarningnparmetroadicionalaalanotacin.Muchosdesarrolladoresusanlaanotacin @Transactional sintomarseel
tiempodecomprenderloquehace.Porejemplo,cuandoseusalaanotacin @Transactional porsisola,comoenelejemplo
anterior,culeselmododepropagacin?Enquvalorestelflagdeslolectura?Culeselniveldeaislamiento?Ms
importante,cundoserealizaunrollback?Esimportantecomprendercmofuncionaestaanotacinparaasegurarnosdeusarel
soportecorrectodetransaccionesennuestraaplicacin.Yentonces,respondiendoatodasestaspreguntas:cuandoseusala
anotacin @Transactional sinningnparmetro,elmododepropagacines REQUIRED ,elflagdeslolecturaes false ,elnivelde
aislamientodelatransaccines READ_COMMITTED ,ylatransaccinnovaarealizarunrollbacksobreunaexcepcinnochequeada(o
sea,quenoseade java.lang.RuntimeException ).

Problemas comunes con el flag de slo-lectura de

@Transactional

Unproblemacomneselusoincorrectodelflagdeslolecturadelaanotacin @Transactional deSpring.Veamosalgunos


ejemplos.

Usodeslolecturaconpropagacin SUPPORTS enJDBC


Unapreguntarpida:siusamoscdigoJDBCestndardparalapersistencia,quhacelaanotacincuandoelflagdeslolectura
esten true yelmododepropagacinen SUPPORTS ?Veamoselejemplo:

@Transactional(readOnly=true,propagation=Propagation.SUPPORTS)

publiclonginsertTrade(TradeDatatrade)throwsException{
//cdigoJDBCac...
}

Sabsquocurre?Aver,vamosconunasopciones.Cuandoseejecutaelmtododelejemploanterior:
A.Selanzaunaexcepcinindicandoqueesunaconexindeslolectura
B.Seinsertacorrectamentelaordendecompraysehaceelcommit
C.Nosehacenadaporqueelniveldepropagacinesten SUPPORTS
Terends?LaopcincorrectaesB.Laordendecompraseinsertacorrectamenteenlabasededatos,inclusoaunqueelflagde
slolecturaestabaen true yelniveldepropagacinen SUPPORTS .Cmopuedeser?Noseiniciningnatransaccinporqueel
mododepropagacinera SUPPORTS ,asqueelmtodouselmododetransaccioneslocales(debasededatos).Yelflagdeslo
lecturasloaplicasiseiniciaunatransaccin.Enestecaso,noseiniciningunatransaccin,asqueseignorelflag.

Usodeslolecturaconpropagacin REQUIRED enJDBC


Vamosconotraoportunidad.Quhacelaanotacin @Transactional cuandoelflagdeslolecturaestactivo,yelmodode
propagacinen REQUIRED ?Comoenesteejemplo:

@Transactional(readOnly=true,propagation=Propagation.REQUIRED)
publiclonginsertTrade(TradeDatatrade)throwsException{
//cdigoJDBCac...
}

Cuandoseejecutaelmtodo insertTrade() loqueocurrees:


A.Selanzaunaexcepcinindicandoqueesunaconexindeslolectura
B.Seinsertacorrectamentelaordendecompraysehaceelcommit
C.Nosehacenadaporqueelflagdeslolecturaesten true
Conlaexplicacinanterior,estavezdeberasermsfacilderesponder.LarespuestacorrectaesA.Oalmenosesloquedebera
ocurrir.Selanzaunaexcepcin,indicandoqueseestintentadorealizarunaoperacindeactualizacinsobreunaconexindeslo
lectura.Comoseinicilatransaccin( REQUIRED ),laconexinseestablecinenslolectura.Asquecuandoseejecutalasentencia
SQL,seobiteneunaexcepcindiciendoquelaconexinesdeslolectura.
Sinembargo,dependiendodelabasededatosqueutilicen,puedequeocurraB:esdecir,queelflagdeslolecturaseaignorado
completamente,ylaconexinsecomportenormalmente.
Loextraodelflagdeslolecturaesquesenecesitainiciarunatransaccinparausarlo.Porqusenecesitaunatransaccinsi

slosevanaleerdatos?Larespuestaesque,enrealidad,nosenecesita.Iniciarunatransaccinpararealizaroperacionesdeslo
lecturaagregarprocesamientoextra,ypuedeocasionarbloqueosdelecturacompartidaenlabasededatos(dependiendodeltipode
basededatosydelniveldeaislamientoqueseuse).Enresumen,elflagdeslolecturanotienemuchosentidocuandoseusa
persistenciausandoJDBC,yocasionaprocesamientoextracuandoseiniciaunatransaccininnecesaria.

Usodeslolecturaconpropagacin REQUIRED enJPA


YqupasacuandousamosunframeworkORM?Siguiendoconesteformatodepreguntas,podrasadivinarcualeselresultadode
laanotacin @Transactional siseusaraenelmtodo insertTrade() queutilizaJPAconHibernate?

@Transactional(readOnly=true,propagation=Propagation.REQUIRED)
publiclonginsertTrade(TradeDatatrade)throwsException{
em.persist(trade);
returntrade.getTradeId();
}

Cuandoseejecutaelmtodo insertTrade() :
A.Selanzaunaexcepcinindicandoqueesunaconexindeslolectura
B.Seinsertacorrectamentelaordendecompraysehaceelcommit
C.Nosehacenadaporqueelflagdeslolecturaesten true
LaopcincorrectaeslaB.Laordendecompraseinsertaenlabasededatossinningnerror.Averunminutoelejemploanterior
nosmostrqueselanzaunaexcepcinporconexindeslolecturacuandoelmododepropagacinera REQUIRED .Estoescierto
cuandoseusaJCBC.CuandoseusaunframeworkORM,elflagdeslolecturaessloun"consejo"paralabasededatosyuna
directivaparaelORM(enestecaso,Hibernate)paraestablecerelmododeflushdelcachdeobjetosa NEVER (Nunca),indicando
queelcachdeobjetosnodebesincronizarseconlabasededatosduranteestaunidaddetrabajo.Sinembargo,elmodode
propagacin REQUIRED tieneprecedenciasobretodoesto,permitiendoalatransaccininiciaryfuncionarcomosinoestuvieraelflag
deslolectura.

UsodeslolecturaenJPA
Loquenosllevaaotroerrorfrecuente.Sabiendotodoesto,culsuponsqueserelresultadodeejecutarelsiguientecdigo,slo
asignandoelvalordelflagdeslolectura?

@Transactional(readOnly=true)
publicTradeDatagetTrade(longtradeId)throwsException{
returnem.find(TradeData.class,tradeId);
}

Elmtodo getTrade() :
A.Iniciaunatransaccin,obtienelaordendecompra,yluegohacecommitdelatransaccin
B.Obtienelaordendecomprasininiciarunatransaccin
LarespuestacorrectaeslaA.Seiniciaunatransaccinysehaceuncommit.Nonosolvidemosqueelmododepropagacinpor
defectodelaanotacin @Transactional es REQUIRED .Estosignificaqueseiniciaunatransaccincuando,enrealidad,nose
necesitabadeuna.Dependiendodelabasededatosqueusemos,estopuedeocasionarbloqueoscompartidosinnecesarios,loque
puederesultarensituacionesdedeadlockenlabasededatos.Adems,seconsumetiempodeprocesamientoyrecursos
innecesariosparainiciarydetenerlatransaccin.
Enresumen,cuandoseusaunframeworkORM,elflagdeslolecturaespracticamenteinutil,yenlamayoradeloscasosseignora.
Perosivamosainsitirconsuuso,siempretenemosqueestablecerelmododepropagacina SUPPORTS ,demaneraquenoseinicie
unatransaccin,comoenelejemplosiguiente:

@Transactional(readOnly=true,propagation=Propagation.SUPPORTS)
publicTradeDatagetTrade(longtradeId)throwsException{
returnem.find(TradeData.class,tradeId);
}

Mejoran,simplementeevitamosusarlaanotacin @Transactional cuandohacemosoperacionesdeslolectura:

publicTradeDatagetTrade(longtradeId)throwsException{
returnem.find(TradeData.class,tradeId);
}

Problemas comunes con el atributo

REQUIRES_NEW

CuandousamosSpringFrameworkoEJB,elmalusodelatributodetransaccin REQUIRES_NEW puedetenerresultadosnegativosy


llevaracorrupcineinconsistenciadedatos.Elatributodetransaccin REQUIRES_NEW siempreiniciaunatransaccinnuevacuando
comienzaelmtodo,existaonounatransaccinencurso.Muchosdesarrolladoresusanalatributo REQUIRES_NEW demanera
incorrecta,asumiendoqueeslaformacorrectadeasegurareliniciodetransacciones.Consideremoslossiguientesdosmtodos:

@Transactional(propagation=Propagation.REQUIRES_NEW)

@Transactional(propagation=Propagation.REQUIRES_NEW)
publiclonginsertTrade(TradeDatatrade)throwsException{...}

@Transactional(propagation=Propagation.REQUIRES_NEW)
publicvoidupdateAcct(TradeDatatrade)throwsException{...}

Ambosmtodossonpblicos,porloquepuedenserinvocadosdeformaindependienteunodelotro.Losproblemassurgenconel
atributo REQUIRES_NEW cuandohaymtodosquelosusandentrodelamismaUnidadLgicadeTrabajoatravsdecomunicacin
entreservicios,ousandoorquestacin.Porejemplo,supongamosqueinvocamosalmtodo updateAcct() deformaindependiente
decualquierotromtodoenalgunoscasosdeuso,perotambinhayuncasodondeelmtodoseinvocadentrodelmtodo
insertTrade() .Ahorabien,siocurreunaexcepcinluegodelainvocacina updateAcct() ,laordendecompravaatenerun

rollback,perosevaarealizaruncommitdelaactualizacinalacuenta.Porejemplo:

@Transactional(propagation=Propagation.REQUIRES_NEW)
publiclonginsertTrade(TradeDatatrade)throwsException{
em.persist(trade);
updateAcct(trade);
//Unaexcepcinocurreac!Laordendecompratieneunrollback,
//perolaactualizacindelacuentano!
...
}

Estoocurreporqueseiniciunatransaccinnuevaenelmtodo updateAcct() ,demaneraqueocurreuncommitcuandoterminael


mtodo updateAcct() .Cuandoseusaelatributodetransaccin REQUIRES_NEW ,sihayuncontextotransaccionalpresente,la
transaccinencursosesuspendeyseiniciaunanuevatransaccin.Unavezqueterminaelmtodo,serealizaelcommitdelanueva
transaccinysecontinuaconlatransaccinoriginal.
Debidoaestecomportamiento,elatributodetransaccin REQUIRES_NEW slodebeusarsesilaaccinsobrelabasededatos
necesitaguardarsesinimportarelresultadodelatransaccinsubyacente.Porejemplo,supongamosquesenecesitaguardaruna
auditoriadecadaintentodeordendecompraqueserealice.Senecesitapersistirestainformacinsinimportarsihuboproblemasde
validacin,fondosinsuficientes,ocualquierotrarazn.Sinousamoselatributo REQUIRES_NEW enelmtododeauditoria,elregistro
deauditoriasufriraunrollbackjuntoconlaordendecomprafallida.Elusodelatributo REQUIRES_NEW garantizaquelosdatosde
auditoriaseguardensinimportarelresultadodelatransaccinoriginal.

Enresumen,siemprehayqueusarlosatributos MANDATORY o REQUIRED enlugarde REQUIRES_NEW amenosquetengamosrazones


parausarlo,pormotivossimilaresaldelejemplodeauditoria.

Problemas comunes con el rollback de transacciones

Problemas comunes con el rollback de transacciones


Porltimovamosaverunodelosproblemasmscomunesconlastransacciones.Desafortunadamenteviestetipodeproblemasen
cdigoproductivomsdeunavez.VamosacomenzarconSpringFramework,yluegoseguimosconEJB3.Hastaahoranuestro
cdigoseveaalgoas:

@Transactional(propagation=Propagation.REQUIRED)
publicTradeDataplaceTrade(TradeDatatrade)throwsException{
try{
insertTrade(trade);
updateAcct(trade);
returntrade;
}catch(Exceptionup){
//logdelerror
throwup;
}
}

Supongamosquelacuentanotienefondossuficientespararealizarlaoperacinencuestin,onoesthabilitadatodava,ylanza
unaexcepcinchequeada(porejemplo,una FundsNotAvailableException ).Sepersistelaordendecomprasenlabasededatos,o
sesehaceunrollbackdetodalaunidaddetrabajo?Larespuesta,sorprendentemente,esquesobreunaexcepcinchequeada
(tantoenSpringFrameworkcomoenEJB),sehacecommitsobrelatransaccin.Estosignificaquesiocurreunaexcepcin
chequeadadurantelaejecucindelmotdo updateAcct() ,laordendecompraigualserpersistida,perolacuentanovaaestar
actualizadareflejandolaoperacin.
Quizsestasealaprincipalcausadelosproblemasdeintegridadyconsistenciadedatos.LasexcepcionesdeRuntime(esdecir,las
nochequeadas)fuerzanunrollbackautomticosobretodalaunidaddetrabajo,perolasexcepcioneschequeadasno.Esporesto
que,enelcdigoanterior,latransaccinesinutilapesardequepareceusarunatransaccinparamanteneratomicidady
consistencia,enlarealidadnolohace.
Aunqueestecomportamientopuedaparecerextrao,hayvariosbuenosmotivosparaquelastransaccionesfuncionenas.Primero,
notodaslasexcepcioneschequeadasson"malas"puedenusarseparaidentificacindeeventosopararedirigirelprocesamiento
basndoseenciertascondiciones.Peroadems,elcdigodelaaplicacinpodratomarmedidascorrectivasenalgunasexcepciones
chequeadas,ypermitirquelatransaccinsecomplete.Porejemplo,consideremoselescenarioendondeescribimoscdigoparaun
sitiodeventadelibros.Paracompletarlaordendecompradelibros,necesitamosenviarunemaildeconfirmacincomopartedel
proceso.Sielservidordemailestcaido,selanzaralgntipodeexcepcinchequeadaindicandoqueelmensajenopudoenviarse.
Silasexcepcioneschequeadascausaranunrollbackautomtico,todalaordendecompratendraunrollbackporqueelservidorde
mailestcaido.Alnorealizarunrollbackautomticosobreexcepcioneschequeadas,podemosatraparlaexcepcinyrealizaralguna
accincorrectiva(comoenviarelmensajeaunacoladependientes),yrealizaruncommitdelrestodelaorden.

accincorrectiva(comoenviarelmensajeaunacoladependientes),yrealizaruncommitdelrestodelaorden.
CuandoseusaunmodelotransaccionalDeclarativo,debemosindicarcmoelcontenedoroelframeworkvaamanejaralas
excepciones.EnSpringFrameworkespecificamoselparmetro rollbackFor enlaanotacin @Transactional ,comovemosa
continuacin:

@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
publicTradeDataplaceTrade(TradeDatatrade)throwsException{
try{
insertTrade(trade);
updateAcct(trade);
returntrade;
}catch(Exceptionup){
//logdelerror
throwup;
}
}

Veamoselusodelparmetro rollbackFor paralaanotacin @Transactional .Esteparmetroaceptatantounanicaexcepcin


comounarraydeexcepciones,opodemosusarelparmetro rollbackForClassName paraespecificarlosnombresdelas
excepcionescomoString.Tambinpodemosusarlaversin"negativa"deestapropiedad( noRollbackFor )paraindicarquetodaslas
excepcionesfuerzanunrollbackmenosalgunasespecficas.Usualmente,lamayoradelosdesarrolladoresutilizanelvalor
Exception.class ,indicandoquetodaslasexcepcionesdelmtododebenforzarunrolklback.

LosEJBfuncionanalgodiferenteaSpringencuantoalrollbackdetransacciones.Laanotacin @TransactionAttribute deEJB3.0


noincluyedirectivasparaespecificarelcomportamientodelrollback.Encambio,sedebeusarelmtodo
SessionContext.setRollbackOnly() paramarcaralatransaccinparahacerrollback,comovemosacontinuacin:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
publicTradeDataplaceTrade(TradeDatatrade)throwsException{
try{
insertTrade(trade);
updateAcct(trade);
returntrade;
}catch(Exceptionup){
//logdelerror
sessionCtx.setRollbackOnly();
throwup;
}

}
}

Unvezqueseinvocaalmtodo setRollbackOnly() nopodemoscambiardeparecerelnicoresultadoposibleeselrollbackdela


transaccinluegodequesecompletelaejecucindelmtodoquelainici.

Conclusin
ElcdigoqueseusaparaimplementartransaccionesesJavanoesmuycomplejosinembargo,puederesultarcomplejosu
utilizacin.HayvarioserrorescomunesasociadosconlaimplementacindelsoportetransaccionalenJava.Elmayorproblemaesque
nohayningnavisodelcompiladoroentiempodeejecucindequelaimplementacindelatransaccinesincorrecta.Msan,
implementarelsoportedetransaccionesnoesslounejerciciodecodificacin.Sedebededicarunesfuerzoimportanteaestablecer
laestrategiatransaccionalgeneral.

BasadoenTransactionstrategies:Understandingtransactionpitfalls

Das könnte Ihnen auch gefallen