chegando javax.persistência.TransactionRequiredException em um recipiente Entidade gerenciada Manager

StackOverflow https://stackoverflow.com//questions/24001269

  •  20-12-2019
  •  | 
  •  

Pergunta

Oi eu criei um simples JSF + JPA aplicação.minha web app consiste em um Entity, um ManagedBean e alguns JSF páginas.A sua finalidade é criar e armazenar um objeto no banco de dados MySQL.Eu fico javax.persistence.TransactionRequiredException toda vez que eu quiser manter a entidade em PersistenceContxt.No entanto, quando injectada UserTransaction para a classe de controlador funciona sem qualquer problema, mas eu não consigo entender por quê?Porque é suposto não precisa adicionar UserTransaction porque é container gerenciado.Estou errado ou o que?ou há outros problemas em meus códigos?

Aqui é o meu ManagedBean código:

@ManagedBean
@SessionScoped
public class Controller {
    @PersistenceContext
    private EntityManager em;
    private Book book;
    public Controller() {}

    public Book getBook() {
        return book;
    } 

    public void setBook(Book book) {
        this.book = book;
    }

    public String createBook() {
        book = new Book();
        return "create";
    }

    public String showResponse() {
        em.persist(book);
        return "response";
    }
}

Aqui é o create.xhtml facelet:

...
<h:form>
    <h:panelGrid columns="2">
        <h:outputText>Title</h:outputText>
        <h:inputText value="#{controller.book.title}" />
    </h:panelGrid>
</h:commandButton action="#{controller.showResponse()}" value="Response" />
...

e este é o Persistence.xml conteúdo:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="JPATestPU" transaction-type="JTA">
    <jta-data-source>jdbc/mysql</jta-data-source>
    <properties>
      <property name="javax.persistence.schema-generation.database.action" value="create"/>
    </properties>
  </persistence-unit>
</persistence>
Foi útil?

Solução

A transação é automaticamente criado apenas para métodos de EJB, não para is better gerido feijão.Se você está em JEE7 recipiente que você pode tentar adicionar @Transacional para o seu Controlador de managed bean, caso contrário, você precisará usar UserTransation para gerenciar a transação.

Aqui é um pedaço de código que eu usei:

@Transactional
public class PersonService {
    @PersistenceContext 
    private EntityManager em;

    public void savePerson(Person person) {
    em.persist(person);
}

E eu estou chamando o servlet:

 @WebServlet("/MyServlet")
 public class MyServlet extends HttpServlet {
    @Inject
    PersonService service;
  ....
  service.savePerson(p);
  System.out.println("Person saved");

Eu posso ver em banco de dados que foi salvo, e nos registros vejo seguintes mensagens:

INFO: Managed bean with Transactional annotation and TxType of REQUIRED called outside a transaction context.  Beginning a transaction...
INFO: Person saved

Então, como você pode ver nova transação é engaiolados e objeto é salvo

Outras dicas

Tendo olhado para o snippet de código.Eu acho que isso é sim um problema de design de um problema técnico.Eu sugiro que você deve considerar a estruturação de sua aplicação como a seguir:1.Camada de banco de dados - MySql.2.Entidades pacote contém objetos de entidade que mapeiam diretamente para as tabelas de banco de dados.3.Objectos de Acesso a dados de Pacote contém EJBs (e.g.@Singleton, @Stateless, @Stateful).4.Controlador de Pacote contém o servlet e/ou geridos feijão, que são acessados pela camada de apresentação através de EL(e.g.@Nome, @ConversionScoped, @ManagedBean, etc) 5.Camada de apresentação - JSF páginas (e.g.o índice.xhtml, etc.)

É importante para a estrutura de seu código dessa forma, pois as transações e segurança e outros serviços são fornecidos automaticamente para EJBs que é onde a persistência deve ser realizada.Que é, de referência para o EntityManager (através do @PersistenceContext)deve ser feita em EJBs não no Managed Beans objetos.Os objetos em que o controlador deve usar o @Injetar (@EJB) anotações para injetar dependências.

A menos que a operação é de leitura do banco de dados, apenas uma coisa que você precisa é de "@Transacional" anotação acima de seu método.Você também pode defini-lo acima de sua classe.Mas não é a arquitetura própria.Pelo menos você tem que criar uma outra classe e injetá-lo no seu feijão.

Se você estiver usando o JavaEE, você deve usar EJB.É fácil e você não precisa se preocupar sobre a transação.O recipiente pode controlar a coisa toda.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top