obtenir javax.la persistance.TransactionRequiredException dans une gérée par le conteneur Gestionnaire d'Entité

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

  •  20-12-2019
  •  | 
  •  

Question

Salut j'ai créé un simple JSF + JPA application.mon application web se compose d'un Entity, un ManagedBean et certains JSF des pages.Il a pour but de créer et de stocker un objet dans la base de données MySQL.Je reçois javax.persistence.TransactionRequiredException chaque fois que je veux conserver l'entité dans le PersistenceContxt.Cependant lors de l'injection de l' UserTransaction dans la classe controller, il fonctionne sans aucun problème, mais je ne comprends pas pourquoi?Parce qu'il est censé nécessité de ne pas ajouter UserTransaction parce qu'elle est gérée par le conteneur.Je me trompe ou quoi?ou il y a d'autres questions dans mes codes?

Voici mon ManagedBean code:

@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";
    }
}

Ici, c'est le 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" />
...

et c'est le Persistence.xml contenu:

<?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>
Était-ce utile?

La solution

La Transaction est automatiquement créé uniquement pour les méthodes de l'EJB, pas pour manged haricots.Si vous êtes dans JEE7 conteneur, vous pouvez essayer d'ajouter @Transactional à votre Contrôleur de managed bean, sinon vous devez utiliser UserTransation de gérer la transaction.

Voici le morceau de code que j'ai utilisé:

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

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

Et je suis d'appel de la servlet:

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

Je peux voir dans la base de données qu'il a été enregistré, et dans les logs je vois des messages suivants:

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

Donc, comme vous pouvez le voir nouvelle transaction est créée et l'objet est enregistré

Autres conseils

Après avoir regardé l'extrait de code.Je pense que c'est plutôt un problème de conception que d'un problème technique.Je suggère que vous devriez envisager de structurer votre application comme suit:1.Couche de base de données - MySql.2.Les entités paquet contient des objets de l'entité que la carte directement à vos tables de base de données.3.Objets d'Accès aux données - Paquet contient les Ejb (par ex.@Singleton, @Stateless @Stateful).4.Contrôleur Paquet contient la servlet et/ou gérés, les fèves, qui sont accessibles par la couche de présentation à travers EL(par ex.@Nommé, @ConversionScoped, @ManagedBean, etc) 5.La couche présentation - pages JSF (par ex.index.xhtml, etc)

Il est important de structurer votre code de cette façon parce que les transactions et la sécurité et d'autres services sont automatiquement fournis pour les Ejb qui est l'endroit où la persistance doit être effectuée.Qui est, la référence à l'EntityManager (via @PersistenceContext)doit être faite dans les Ejb pas dans la gestion des Haricots objets.Les objets dans le contrôleur doit utiliser @Inject (@EJB) les annotations de injecter les dépendances.

À moins que votre opération est à lire à partir de la base de données, une seule chose que vous avez besoin est de "@Transactionnelle" annotation au-dessus de votre méthode.Aussi, vous pouvez le définir au-dessus de votre classe.Mais ce n'est pas la bonne architecture.Au moins, vous devez créer une autre classe et de l'injecter sur votre bean.

Si vous utilisez JavaEE, vous devez utiliser des EJB.Il est facile et vous n'avez pas besoin de s'inquiéter à propos de la transaction.Conteneur de contrôle de toute chose.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top