2016-04-18 10 views
0

Ich losted viele Zeit versuchen, diesen Aussteller zu lösen, aber ich bin an der gleichen Stelle. Ich vermute, dass ich etwas von CDI mit EJB gemischt habe.WFLYJPA0060: Transaktion ist erforderlich, um diese Operation durchzuführen (entweder einen Transaktions- oder erweiterten Persistenzkontext verwenden)

Das Problem ist persistent und löschen nur nicht funktionieren.

Caused by: javax.persistence.TransactionRequiredException: WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context) 
    at org.jboss.as.jpa.container.AbstractEntityManager.transactionIsRequired(AbstractEntityManager.java:866) 
    at org.jboss.as.jpa.container.AbstractEntityManager.persist(AbstractEntityManager.java:579) 
    at com.oki.scope.console.model.dao.GenericDAO.save(GenericDAO.java:29) 
    at com.oki.scope.console.model.dao.GenericConsoleDAO.save(GenericConsoleDAO.java:12) 
    at com.oki.scope.console.service.ServidorServiceImp.salvar(ServidorServiceImp.java:27) 
    at com.oki.scope.console.service.ServidorServiceImp$Proxy$_$$_WeldClientProxy.salvar(Unknown Source) 
    at com.oki.scope.console.managedBean.consulta.ServidorMB.salvar(ServidorMB.java:65) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at com.sun.el.parser.AstValue.invoke(AstValue.java:292) 
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304) 
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40) 
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) 
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40) 
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) 
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) 
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87) 
    ... 40 more 

Mein DAO

public class GenericDAO<T, K> { 

    protected EntityManager em; 
    private Class<T> entityClass; 

    public GenericDAO(Class<T> entityClass, EntityManager em) { 
     this.entityClass = entityClass; 
     this.em = em; 
    } 

    @Transactional 
    protected void save(T entity) { 
     em.persist(entity); 
    } 

Generisches DAO:

import javax.persistence.EntityManager; 

public abstract class GenericConsoleDAO<T, K> extends GenericDAO<T, K> { 

    public GenericConsoleDAO(Class<T> entityClass, EntityManager em) { 
     super(entityClass, em); 
    } 

    public void save(T t){ 
     super.save(t); 
    } 

} 

DAO Factory:

package com.oki.scope.console.model.dao; 

import java.lang.reflect.InvocationTargetException; 
import java.util.Collections; 
import java.util.HashMap; 
import java.util.Map; 

import javax.ejb.Singleton; 
import javax.ejb.TransactionManagement; 
import javax.ejb.TransactionManagementType; 
import javax.enterprise.inject.Produces; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 

@Singleton 
@TransactionManagement(TransactionManagementType.CONTAINER) 
public class DAOConsoleFactory { 
    private final static String UNIT_NAME = "scope-console"; 

    private static Map<String, Object> mapa = Collections.synchronizedMap(new HashMap<String, Object>()); 

    @PersistenceContext(unitName = UNIT_NAME) 
    private EntityManager entityManager; 

    @Produces public ServidorDAO   criaServidorDAO(){   return getDAO(ServidorDAO.class); } 
    @Produces public ConexaobdDAO   criaConexaoDAO(){   return getDAO(ConexaobdDAO.class);  } 
    @Produces public ContratoDAO   criaContratoDAO(){   return getDAO(ContratoDAO.class); } 
    @Produces public EmpresaDAO    criaEmpresaDAO(){   return getDAO(EmpresaDAO.class); } 
    @Produces public LojaDAO    criaLojaDAO(){    return getDAO(LojaDAO.class); } 
    //@Produces public RedeAutorizadoraDAO criaRedeAutorizadoraDAO(){ return getDAO(RedeAutorizadoraDAO.class); } 
    @Produces public RedeDAO    criaRedeDAO(){    return getDAO(RedeDAO.class); } 
    @Produces public RoteadorDAO   criaRoteadorDAO(){   return getDAO(RoteadorDAO.class); } 
    @Produces public TerminalDAO   criaTerminalDAO(){   return getDAO(TerminalDAO.class); } 
    @Produces public TipoHeaderDAO   criaTipoHeaderDAO(){  return getDAO(TipoHeaderDAO.class);  } 

    @SuppressWarnings("unchecked") 
    public <E> E getDAO(Class<E> classe){ 
     String key = classe.getSimpleName(); 
     if (!mapa.containsKey(key)) 
     { 
      try { 
       mapa.put(key, classe.getDeclaredConstructor(EntityManager.class).newInstance(entityManager)); 
      } catch (InstantiationException | IllegalAccessException | IllegalArgumentException 
        | InvocationTargetException | NoSuchMethodException | SecurityException e) { 
       System.out.println("Classe "+ key +" não possui um construtor que tenha EntityManager como parametro."); 
      } 
     } 
     return (E)mapa.get(key); 

    } 
} 

Meine Klasse:

@Named 
@ApplicationScoped 
public class ServidorServiceImp implements ServidorService { 

    @Inject private ServidorDAO dao; 


    @Override 
    public List<Servidor> getLista() { 
     return dao.getLista(); 
    } 

    @Override 
    public void salvar(Servidor servidor) { 
     if (servidor.getId()==0){ 
      dao.save(servidor); 
     } 
     else 
     { 
      dao.update(servidor); 
     } 
    } 

    @Override 
    public void remover(Servidor servidor) { 
     dao.delete(servidor); 

    } 

} 

Antwort

2

In dem Bemühen, die Leistung zu verbessern, haben Sie umgangen, was der Container für Sie tun soll, die eine Bean innerhalb einer Transaktion instanziiert.

Ich würde sagen, die @Singleton und @TransactionManagement(TransactionManagementType.CONTAINER) von DAOConsoleFactory entfernen und der EJB Transaktion ermöglicht durch den EJB-Bean behandelt werden, die die DAO sind verwenden.

UPDATE: Auch ist @ApplicationScoped kein EJB Annotation-Klasse ServidorServiceImp so ein EJB Bean sein muss, sollte es mit @Stateless oder vielleicht @Statefull und entfernen Sie die @ApplicationScoped mit Anmerkungen versehen werden. Es liest sich wie eine zustandslose EJB-Bean, daher muss es nicht auf Anwendungsbereiche beschränkt werden.

Wieder scheint es, dass Sie sich zu sehr darauf konzentrieren, die Leistung zu optimieren, ohne ein gutes Verständnis dafür zu haben, wie EJBs in einem Container funktionieren sollen. Ich würde empfehlen, alles zum Laufen zu bringen und den Best Practices der Architektur zu folgen, besonders im Konzept "Session Façade". Einige dieser Beiträge können helfen: What is the point of a Facade in Java EE? oder Why use Facade pattern for EJB session bean.

+0

Ich entfernte die beiden Noten. Das beweist, dass @TransactionManagement nicht verwendet wurde. Das Problem bleibt gleich. –

+0

Updates hinzugefügt, um zu antworten. –

1

Gelöst: Vor 2 Tagen leiden. Das Problem war in meiner Klasse. Wo ist @Named @ApplicationScoped, ich wechselte zu @Statefull.

+1

Hallo Kumpel, es könnte unhöflich klingen, aber Ihre Implementierungen sind sehr schlecht. Sehen Sie sich dieses Buch an (http://realworldpatterns.com/) und Sie werden alle missbrauchten Muster und den Code, den Sie haben, verstehen. Ich empfehle Ihnen die Kapitel zu DAO und SessionBean und Fassadenmustern. –