Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Envolver inserções em uma transação (transaction, roollback, commit)

Estou persistindo em mais de uma tabela, e se houver algum erro eu quero que de um rollback em tudo.

em Java com Spring consigo fazer isso de forma simples apenas anotando o método da service @Transact..., como poderia fazer isso com mysql node, li a documentação mas ficou meio confuso, esse é meu projeto que fiz acompanhando o curso usando a mesma estrutura, como poderia ser feito com transações nessa estrutura ?

// queries.js
const conexao = require('./conexao')

const executaQuery = (query, parametros = '') => {
    return new Promise((resolve, reject) => {
        conexao.query(query, parametros, (erro, resultados, campos) => {
            if (erro) {
                reject(erro)
            } else {
                resolve(resultados)
            }
        })
    })

}

module.exports = executaQuery
// post
const query = require('../infra/database/queries')

class PostRepository {

    adiciona(post) {
        const sql = 'INSERT INTO post SET ?'
        return query(sql, post)
    }

    lista() {
        const sql = 'SELECT * FROM post';
        return query(sql)
    }
}
module.exports = new PostRepository()

e por fim onde eu gostaria de o método ficar em uma trancação, " adiciona post", também adiciono as categorias mas se houver algum erro, quero dar rollback, pois já havia salvo o post, tem como me mostrar o caminho das pedras?

const PostRepository = require('../repositories/postRepository')
const AutorService = require('../services/autorService')
const Campo = require('../model/campo')
const PostCategoriasService = require('../services/PostCategoriasService')

class PostService {
// transactional
    async adiciona(post) {
// inicia transacao
        const autor = await AutorService.buscarPorId(parseInt(post.autorId))

        if (!autor) return Promise.reject(new Campo('autorId', 'id do autor inválido'))

        if (!post.categoriasId.length) return Promise.reject(new Campo('categoriasId', 'nenhuma categoria selecionada'))

        const categoriasId = post.categoriasId
        delete post.categoriasId

        post.criadoEm = new Date()

        const resultadosPost = await PostRepository.adiciona(post) // 1° insert
        const id = resultados.insertId

        const resultadosCtg = await PostCategoriasService.adicianAll(id, categoriasId) // 2° insert
// houve algum erro, rollback
// não houve, commit
        return { ...post, id }
    }

    lista() {
        return PostRepository.lista()
    }
}

module.exports = new PostService()
1 resposta
solução!

Vou postar a solução aqui caso alguém mais precise: Mudei a forma de administrar a conexão com o banco, implementei uma que estava no blog do cangaceiro, link: http://cangaceirojavascript.com.br/lidando-com-conexoes-banco-plataforma-node/

Depois disso, só passar a conexão, como parâmetro, essa mesma será usada durante a requisição, ficando assim:

//PostService
    async adiciona(conexao, post) {

        await conexao.beginTransaction() // inicia uma transação

        try {

            if (!post.categoriasId.length) return Promise.reject(new Campo('categoriasId', 'nenhuma categoria selecionada'))

            const autor = await AutorService.buscarPorId(conexao, parseInt(post.autorId))
            if (!autor) return Promise.reject(new Campo('autorId', 'id do autor inválido'))

            const categoriasId = post.categoriasId
            delete post.categoriasId
            let tagsId = []
            if (post.hasOwnProperty('tagsId')) {
                tagsId = post.tagsId
            }
            delete post.tagsId

            post.criadoEm = new Date()
            post.publicadoEm = post.publicado ? new Date() : null

            const resultadosPost = await PostRepository.adiciona(conexao, post)
            const id = resultadosPost.insertId

            await PostCategoriasService.adicianaAll(conexao, id, categoriasId)

            if (tagsId.length) {
                await PostTagService.adicianaAll(conexao, id, tagsId)
            }

            await conexao.commit() // deu tudo certo, commita

            return Promise.resolve({ ...post, id })

        } catch (error) {
            logger('log.log').error('erro ao adicionar post ' + error)
            await conexao.rollback();  // deu algum erro rollback
            return Promise.reject(error);
        }
    }

Funcionando perfeitamente!!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software