简体   繁体   English

小面应用程序中的javax.persistence.TransactionRequiredException

[英]javax.persistence.TransactionRequiredException in small facelet application

I'm trying to persist some values to a MySql database from a small facelet application but keep getting this error. 我试图从一个小的facelet应用程序中将一些值持久化到MySql数据库中,但一直收到此错误。 I had this same application with a JPS page and a servlet and it worked fine with roughly the same logic, this is my first time trying to work with facelets so it might just be something silly but i'd appriciate the help. 我有一个具有JPS页面和servlet的相同应用程序,并且在大致相同的逻辑下也可以正常工作,这是我第一次尝试使用facelets,因此可能有些愚蠢,但我会寻求帮助。

Thanks 谢谢

error 错误

javax.faces.el.EvaluationException: javax.persistence.TransactionRequiredException
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    at javax.faces.component.UICommand.broadcast(UICommand.java:315)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722)
Caused by: javax.persistence.TransactionRequiredException
    at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163)
    at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:145)
    at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:263)
    at vecka19.controller.BookController.addBook(BookController.java:28)
    at vecka19.controller.BookController$Proxy$_$$_WeldClientProxy.addBook(BookController$Proxy$_$$_WeldClientProxy.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:779)
    at javax.el.BeanELResolver.invoke(BeanELResolver.java:528)
    at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:257)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:248)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:39)
    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:88)
    ... 32 more

index.xhtml index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
    <title>Vecka19</title>
</h:head>
<h:body>
    <section id="bookForm">
        <div>
            <h:form id="bookForm">
                <table>
                    <tr>
                        <td><h:outputLabel value="ID: " for="id"/></td>
                        <td><h:inputText id="id" value="#{book.bookId}"/></td>
                    </tr>
                    <tr>
                        <td><h:outputLabel value="TITLE: " for="title"/></td>
                        <td><h:inputText id="title" value="#{book.title}"/></td>
                    </tr>
                    <tr>
                        <td><h:outputLabel value="AUTHOR: " for="author"/></td>
                        <td><h:inputText id="author" value="#{book.author}"/></td>
                    </tr>
                    <tr>
                        <td><h:outputLabel value="PRICE: " for="price"/></td>
                        <td><h:inputText id="price" value="#{book.price}"/></td>
                    </tr>
                    <tr>
                        <td>
                            <h:commandButton value="Add" action="#{bookController.addBook()}" />
                            <h:commandButton value="Get" action="#{bookController.book}" />
                            <h:commandButton value="Edit" action="#{bookController.editBook()}" />
                            <h:commandButton value="Delete" action="#{bookController.deleteBook()}" />
                        </td>
                    </tr>
                </table>
            </h:form>
        </div>
    </section>
    <br />
    <section id="dbTable">
        <div>
            <table>
                <th>ID</th>
                <th>TITLE</th>
                <th>AUTHOR</th>
                <th>PRICE</th>
                <c:forEach items="${bookController.books}" var="book">
                    <tr>
                        <td>${book.bookId}</td>
                        <td>${book.title}</td>
                        <td>${book.author}</td>
                        <td>${book.price}</td>
                    </tr>
                </c:forEach>
            </table>
        </div>
    </section>
</h:body>

BookController.java BookController.java

package vecka19.controller;

import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import vecka19.model.Book;

@Named
@RequestScoped
public class BookController {
    @Inject Book book;

    @PersistenceContext
    private EntityManager em;

    public List getBooks() {
        return em.createNamedQuery("Book.findAll").getResultList();
    }

    public Book getBook() {
        return em.find(Book.class, book.getBookId());
    }

    public void addBook() {
        em.persist(book);
    }

    public void editBook() {
        em.merge(book);
    }

    public void deleteBook() {
        em.remove(getBook());
    }

}

Book.java Book.java

package vecka19.model;

import java.io.Serializable;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

@Entity
@Named
@RequestScoped
@Table(name = "BOOKS")
@NamedQueries({@NamedQuery(name = "Book.findAll", query = "SELECT b FROM Book b")})
public class Book implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @NotNull
    @Column(name = "BOOK_ID")
    private Integer bookId;
    @Column(name = "TITLE")
    private String title;
    @Column(name = "AUTHOR")
    private String author;
    @Column(name = "PRICE")
    private Integer price;

    public Book() {
    }

    public Book(Integer bookId) {
        this.bookId = bookId;
    }

    public Integer getBookId() {
        return bookId;
    }

    public void setBookId(Integer bookId) {
        this.bookId = bookId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }
}

percistence.xml percistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="vecka19PU" transaction-type="JTA">
    <jta-data-source>jdbc/MySQLDataSource</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties/>
  </persistence-unit>
</persistence>

You're abusing a CDI managed bean as a business service. 您正在滥用CDI托管的bean作为业务服务。 It has no clues of transaction management. 它没有交易管理的线索。 You'd need to manually manage transactions. 您需要手动管理交易。 As this is usually a pain and you're apparently using Glassfish, which is a fullworthy Java EE container supporting EJBs, you'd rather like to use a fullworthy EJB for this. 因为这通常很麻烦,并且您显然正在使用Glassfish,它是支持EJB的完全有价值的Java EE容器,所以您希望为此使用完全有价值的EJB。 When using EntityManager inside an EJB, the container will fully transparently manage DB transactions. 在EJB中使用EntityManager ,容器将完全透明地管理数据库事务。 One EJB method call counts as a single transaction (ie when you fire multiple DB queries and one of them fails, then everything will be automatically rolled back). 一个EJB方法调用计为一个事务(即,当您触发多个数据库查询而其中一个失败时,所有内容将自动回滚)。

Overall, you seem to be mixing the responsibilities of the model, controller and service. 总的来说,您似乎在混合模型,控制器和服务的职责。 Do not make your entity a managed bean as well. 也不要使您的实体成为托管bean。 You should further absolutely also not perform business logic in a Javabean getter method (eg getBooks() ). 您还应该绝对不要在Javabean getter方法中执行业务逻辑(例如getBooks() )。 When referenced in an iterating component, it's invoked during every iteration round. 在迭代组件中引用时,将在每个迭代回合中调用它。 So imagine that you've 100 records, then the DB will be hit 100 times. 因此,假设您有100条记录,那么数据库将被命中100次。 This is plain inefficient. 这显然是低效的。

Here's how it should all look like: 看起来应该像这样:

Model (the entity): 模型(实体):

@Entity
@Table(name = "BOOKS")
public class Book implements Serializable {
    // ...
}

Controller (the backing bean): 控制器(辅助bean):

@Named
@RequestScoped
public class BookController {

    private Book book;
    private List<Book> books;

    @EJB
    private BookService service;

    @PostConstruct
    public void init() {
        book = new Book();
        books = service.list();
    }

    public void add() {
        service.save(book);
        init();
    }

    public Book getBook() { 
        return book;
    }

    public List<Book> getBooks() {
        return books;
    }

}

Service (the EJB): 服务(EJB):

@Stateless
public class BookService {

    @PersistenceContext
    private EntityManager em;

    public List<Book> list() {
        return em.createQuery("FROM Book", Book.class).getResultList();
    }

    public Book find(Integer id) {
        return em.find(Book.class, id);
    }

    public Integer save(Book book) {
        em.persist(book);
        return book.getId();
    }

    public void update(Book book) {
        em.merge(book);
    }

    public void delete(Book book) {
        em.remove(em.contains(book) ? book : em.merge(book));
    }

}

View (the Facelet; simplified): 视图(Facelet;简化):

<h:inputText id="title" value="#{bookController.book.title}"/>
<h:inputText id="author" value="#{bookController.book.author}"/>
<h:inputText id="price" value="#{bookController.book.price}"/>
<h:commandButton value="Add" action="#{bookController.add}" />
...
<h:dataTable value="#{bookController.books}" var="book">
    <h:column><f:facet name="header">ID</f:facet>#{book.id}</h:column>
    <h:column><f:facet name="header">Title</f:facet>#{book.title}</h:column>
    <h:column><f:facet name="header">Author</f:facet>#{book.author}</h:column>
    <h:column><f:facet name="header">Price</f:facet>#{book.price}</h:column>
</h:dataTable>

(your edit and delete buttons didn't make any sense, so I removed them, you might want to put them inside the data table) (您的编辑和删除按钮没有任何意义,因此我将其删除了,您可能希望将其放入数据表中)

See also: 也可以看看:

Just add @Transactional annotation on your method, eg 只需在您的方法上添加@Transactional批注,例如

@Transactional // <-------------
public long setSessionState(StateEnum state, String hash) {

    QSession s = QSession.session;
    JPAUpdateClause upd = new JPAUpdateClause(em, s);
    upd.set(s.state, state).where(s.hash.eq(hash));
    return upd.execute();
}

The javadoc for EntityManager#persist(Object) says EntityManager#persist(Object)的Javadoc说

Throws: TransactionRequiredException - if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction 抛出: TransactionRequiredException-如果在类型为PersistenceContextType.TRANSACTION的容器管理的实体管理器上调用,并且没有事务

You need to call EntityManager.html#getTransaction() and begin a transaction before you call persist (and some of the other methods). 您需要先调用EntityManager.html#getTransaction()开始事务,然后再调用persist(以及其他一些方法)。 Don't forget to also commit or rollback the transaction when you are done. 完成后,别忘了还要commitrollback事务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 javax.persistence.TransactionRequiredException: - javax.persistence.TransactionRequiredException: 在 Spring 启动应用程序中获取“javax.persistence.TransactionRequiredException:没有正在进行的事务” - Getting “javax.persistence.TransactionRequiredException: no transaction is in progress” in Spring Boot Application 更新/删除查询中的javax.persistence.TransactionRequiredException - javax.persistence.TransactionRequiredException in update/delete query javax.persistence.TransactionRequiredException的可能原因 - Possible causes of javax.persistence.TransactionRequiredException javax.persistence.TransactionRequiredException:当前没有活动的事务 - javax.persistence.TransactionRequiredException: There is no currently active transaction 错误javax.persistence.TransactionRequiredException:没有事务正在进行 - Error javax.persistence.TransactionRequiredException: no transaction is in progress javax.persistence.TransactionRequiredException:PuId =没有活动事务 - javax.persistence.TransactionRequiredException: No active transaction for PuId= 保留在@PostConstruct中:javax.persistence.TransactionRequiredException - Persisting in @PostConstruct: javax.persistence.TransactionRequiredException 启用S​​pring事务,javax.persistence.TransactionRequiredException - Enabling Spring Transactions, javax.persistence.TransactionRequiredException javax.persistence.TransactionRequiredException:Spring 5 中没有正在进行的事务 - javax.persistence.TransactionRequiredException: no transaction is in progress in Spring 5
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM