Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Solucionado (ver solução)

Interceptador de transação com CDI

Boa tarde, no método atualizarSalario existe uma interação na lista, e a chamada do método atualizar é realizada para cada objeto da interação, quando retiro o begin e commit, e adiciono a anotação @Transactional o merge não acontece, e nenhum erro é informado.

public class FuncionarioRepository implements Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    private EntityManager entity;

    @Transactional
    public void salvar(Funcionario funcionario) {

        if (funcionario.getId() == null) {
            entity.persist(funcionario);
            FacesUtil.addInfoMessage("Cadastrado com sucesso!");
        } else {
            entity.merge(funcionario);
            FacesUtil.addInfoMessage("Alterado com sucesso!");
        }
    }

    @Transactional
    public void remover(Funcionario funcionario) {
        try {
            entity.remove(funcionario);
            FacesUtil.addInfoMessage("Removido com sucesso!");
        } catch (Exception e) {
            e.printStackTrace();
            FacesUtil.addErrorMessage("Não foi possível concluir essa operação");
        }
    }

public void autualizarSalario(List<Funcionario> funcionarios) {
        funcionarios.forEach(funcionario -> atualizar(funcionario));
        FacesUtil.addInfoMessage("Salários foram atualizados!");
    }

    // nesse método, se coloco @Transactional, e retiro o begin e o commit, o merge não acontece.
    private void atualizar(Funcionario funcionario) {
        entity.getTransaction().begin();
        entity.merge(funcionario);
        entity.getTransaction().commit();
    }

    public List<Funcionario> listarTodos() {
        TypedQuery<Funcionario> query = entity.createQuery("Select f from Funcionario f order by f.nome", Funcionario.class);
        return query.getResultList();
    }

}
@InterceptorBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {

}
@Interceptor
@Transactional
public class InterceptorTransactional implements Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    private EntityManager entity;

    @AroundInvoke
    public Object contextInterceptor(InvocationContext context) throws Exception {

        entity.getTransaction().begin();
        Object object = context.proceed();
        entity.getTransaction().commit();

        return object;

    }

}
7 respostas

Gilmar não atualiza mesmo? Mais para que você quer esse metodo atualiza sendo que você já tem metodo parecido?

  @Transactional
    public void salvar(Funcionario funcionario) {

        if (funcionario.getId() == null) {
            entity.persist(funcionario);
            FacesUtil.addInfoMessage("Cadastrado com sucesso!");
        } else {
            entity.merge(funcionario);
            FacesUtil.addInfoMessage("Alterado com sucesso!");
        }
    }

Quando cai no else aqui já atualiza seu funcionario, não sei se é pra teste seu projeto ai, mais não é bacana ficar repetindo código que fazem a mesma coisa kkk.

Eu precisei fazer outro método exatamente porque esse não funciona, tive que criar um método apenas para ficar abrindo e fechando uma transação porque a anotação não funciona na interação.

Gilmar, tirá uma duvida, em nenhuma ocasião quando você usa o transctional? Você fez a configuração para isso funcionar né?

no seu beans.xml você tem algo assim né?

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <interceptors>
        <class>br.com.nomeProjeto.gerenciamento.Gerenciador</class>
    </interceptors>


</beans>

Tem né?

Uma outra coisa é você ta usando a anotação certa? Porque existe ja uma anotação chamada @Transactional, da uma olhada certinha se você ta importando do pacote certo.

Sem a configuração no bean, o container subiria? acho que não, mas segue a configuração abaixo.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

  <interceptors>
        <class>com.planner.desafio.util.jpa.InterceptorTransactional</class>
  </interceptors>

</beans>

Quando nada acontecia, foi a primeira coisa que observei foi os imports.

import com.planner.desafio.util.jpa.Transactional;

Eitá que estranho isso ein :(

solução

Adicionei o EntityTransaction e funcionaou, agora a minha dúvida, o que o EntityTransaction tem a mais?

@Interceptor
@Transactional
public class InterceptorTransactional implements Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    private EntityManager entity;

    @AroundInvoke
    public Object contextInterceptor(InvocationContext context) throws Exception {
        EntityTransaction entityTransaction = entity.getTransaction();

        entityTransaction.begin();
        Object object = context.proceed();
        entityTransaction.commit();

        return object;

    }

}

Olá Gilmar, olhando o código, teu método esta

private

senão me engano, @Transactional não funciona em métodos privados.