J'essaie de mettre à jour une ligne dans le tableau A et d'insérer une ligne dans le tableau B. Cela doit se produire en un seul appel. J'utilise Spring JDBC pour y parvenir.
Exemple de code
@Transactional public boolean approveTenant(ApproveTenantRequest approveTenantRequest) throws ApplicationException { LogUtil.debug(logger, "UserManagementDAO - approveTenant - Start"); try { String updateSQL = "UPDATE tenant_master SET isactive=1, last_modified_by=:lastModifiedBy, last_modified_at= now() " + " WHERE tenant_id=:tenantid and tenant_community_id=:cmntId"; MapSqlParameterSource parameters = new MapSqlParameterSource(); parameters.addValue("cmntId", approveTenantRequest.getCommunityId()); parameters.addValue("tenantid", Integer.parseInt(approveTenantRequest.getTenantId())); parameters.addValue("lastModifiedBy", approveTenantRequest.getApprovedBy()); int updateEffectedRows = jdbcTemplate.update(updateSQL, parameters); if(updateEffectedRows==1) { String insertSql= "INSERT INTO users (username,password,isactive,community_id,userrole,created_by)" + " values (:username,:password,1,:community_id,:userrole,:created_by)"; parameters.addValue("username", approveTenantRequest.getEmailId()); parameters.addValue("password", approveTenantRequest.getEmailId()); parameters.addValue("community_id", approveTenantRequest.getCommunityId()); parameters.addValue("userrole", "RESIDENT"); parameters.addValue("created_by", approveTenantRequest.getApprovedBy()); int insertEffectedRows = jdbcTemplate.update(insertSql, parameters); LogUtil.debug(logger, "UserManagementDAO - approveTenant - End"); return insertEffectedRows == 0 ? false : true; }else { throw new ApplicationException("Issue in Approving Tenant, Tenant not exist in master data"); } } catch (DataAccessException dataAccessException) { logger.error("Data Access Exception " + dataAccessException); throw new ApplicationException(dataAccessException.getMessage()); } catch (Exception e) { logger.error("Exception Occured While approving tenant " + e); throw new ApplicationException(e.getMessage()); } }
Ce code présente-t-il un défaut? Est-ce la bonne façon de faire? Pouvez-vous nous suggérer.
3 Réponses :
Assurez-vous simplement qu'ils sont placés sous une seule méthode marquée comme @Transactional
.
Cela dit, lorsque la deuxième mise à jour échoue, la première sera annulée et vous maintiendrez la base de données dans un état cohérent.
Pouvez-vous vérifier mon code. La deuxième mise à jour n'a pas pu être insérée, mais la première mise à jour n'a pas été annulée. Y a-t-il quelque chose qui manque ici?
Je pense que votre ApplicationException
est une exception vérifiée. Spring n'annulera pas la transaction, si la méthode transactionnelle a rejeté l'exception cochée par défaut (uniquement non cochée).
Mais vous pouvez ajouter une annulation manuellement comme ceci:
@Transactional(rollbackFor = ApplicationException.class)
Selon le printemps documentation < / a>
Visibilité de la méthode et @Transactional
Lorsque vous utilisez des proxies, vous devez appliquer l'annotation @Transactional uniquement aux méthodes ayant une visibilité publique. Si vous annotez protégé, méthodes privées ou visibles sur les packages avec l'annotation @Transactional, aucune erreur n'est générée, mais la méthode annotée ne présente pas paramètres transactionnels configurés. Considérez l'utilisation d'AspectJ (voir ci-dessous) si vous avez besoin d'annoter des méthodes non publiques.