user2390827
user2390827

Reputation: 115

Executing Multiple queries (Insert and Update) in single transaction using Spring JDBC template

I am trying to update a row in table A and inserting a row in table B. This need to be happen in single call. I am using spring JDBC to achieve this.

Sample 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());
        }
    }

Does this code has any flaw? Is this correct way of doing? Can you please suggest.

Upvotes: 2

Views: 5213

Answers (3)

Sai prateek
Sai prateek

Reputation: 11926

As per spring documentation

Method visibility and @Transactional

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

Upvotes: 0

Artur Vakhrameev
Artur Vakhrameev

Reputation: 844

I think that your ApplicationException is a checked exception. Spring won't rollback transaction, if transactional method throwed out checked exception by default (only unchecked). But you can add rollback for it manually like this:

@Transactional(rollbackFor = ApplicationException.class)

Upvotes: 0

Maciej Kowalski
Maciej Kowalski

Reputation: 26572

Just make sure these are put under one method that is marked as @Transactional.

Having that, when the second update fails, the first one will be rolled back and you will keep the database in a consistent state.

Upvotes: 5

Related Questions