Problema com Carrinho de Compras no VRaptor usando EntityManager ao invés de Sessão

1 resposta
F

Estou recebendo o erro: br.com.caelum.vraptor.InterceptionException: exception raised, check root cause for details: java.lang.IllegalArgumentException: Entity not managed, quando tento usar refresh na entidade Produto na adaptação do código do Carrinho da apostila FJ28 que fiz para usar JPA. O erro está na linha estoque.recarrega(item.getProduto()); no início do método adiciona do CarrinhoController, onde o método recarrega executa this.manager.refresh(produto);. Onde estou errando?

@Resource
public class CarrinhoController {
	
	private Carrinho carrinho;
	private Estoque estoque;
	private Result result;

	public CarrinhoController(Carrinho carrinho,
			Estoque estoque, Result result) {
		this.carrinho = carrinho;
		this.estoque = estoque;
		this.result = result;
	}
	
	@Get("/carrinho")
	public void visualiza() {
	}
	
	@Post("/carrinho")
	public void adiciona(Item item) {
		estoque.recarrega(item.getProduto());
		carrinho.adiciona(item);
		result.redirectTo(this).visualiza();
	}

	@Delete("/carrinho/{indiceItem}")
	public void remove(int indiceItem) {
		carrinho.remove(indiceItem);
		result.redirectTo(this).visualiza();
	}
}
@Component
public class JPAProdutoDAO implements ProdutoDAO {
	
	private final EntityManager manager;

	public JPAProdutoDAO(EntityManager manager) {
		this.manager = manager;
	}

	@Override
	public void adiciona(Produto produto) {
		//this.manager.getTransaction().begin();
		if (produto.getId() == null) {
			this.manager.persist(produto);
		} else {
			this.manager.merge(produto);
		}
		//this.manager.getTransaction().commit();
	}

	@Override
	public List<Produto> todos() {
		return this.manager.createQuery("select p from Produto p", Produto.class)
				.getResultList();
	}

	@Override
	public Produto buscaPorId(Long id) {
		try {
			return this.manager
					.createQuery("select p from Produto p where p.id = :id",
							Produto.class).setParameter("id", id)
					.getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
	}

	@Override
	public Produto buscaPorNome(String nome) {
		try {
			return this.manager
					.createQuery("select p from Produto p where p.nome = :nome",
							Produto.class).setParameter("nome", nome)
					.getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
	}

	@Override
	public List<Produto> buscaPorPalavraChave(String nome) {
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Produto> query = builder.createQuery(Produto.class);
		Root<Produto> from = query.from(Produto.class);
		TypedQuery<Produto> typedQuery = manager.createQuery(
			    query.select(from )
			    .where( 
			    	builder.like(from.<String>get("nome"), "%"+nome+"%")
			    )
			    .orderBy(builder.asc(from.get("nome")))
			);
		List<Produto> results = typedQuery.getResultList();
		return results;
	}

	@Override
	public List<Produto> buscaPorCategoria(String categoria) {
		try {
			return this.manager
					.createQuery("select p from Produto p where p.categoria = :categoria",
							Produto.class).setParameter("categoria", categoria)
					.getResultList();
		} catch (NoResultException e) {
			return null;
		}
	}
	
	@Override
	public void remove(Produto produto) {
		//this.manager.getTransaction().begin();
		this.manager.remove(produto);
		//this.manager.getTransaction().commit();
	}
	
	@Override
	public void recarrega(Produto produto) {
		this.manager.refresh(produto);
	}
	
}

1 Resposta

Lucas_Cavalcanti

o refresh da JPA precisa que o objeto esteja managed, ou seja, que já tenha sido adicionado/buscado pelo EntityManager.

acho que o que vc quer é o refresh do hibernate, que pega qqer coisa que tenha Id e preenche os objetos.

faça:

manager.unwrap(Session.class).refresh(objeto);
Criado 20 de julho de 2014
Ultima resposta 2 de ago. de 2014
Respostas 1
Participantes 2