Hibernate javax.persistence.RollbackException:提交事务时出错

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24576100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 13:08:19  来源:igfitidea点击:

Hibernate javax.persistence.RollbackException: Error while committing the transaction

javamysqlhibernatejpa

提问by user3159152

I am developing a java web application using Hibernate and MySQL. Sometimes when I try to persist things, I get this rollback exception:

我正在使用 Hibernate 和 MySQL 开发一个 java web 应用程序。有时,当我尝试坚持操作时,我会收到此回滚异常:

javax.persistence.RollbackException: Error while committing the transaction
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:94)
    at com.tulips.dao.CommentDao.saveOrUpdate(CommentDao.java:42)
    at com.tulips.servlets.CommentsServlet.doPost(CommentsServlet.java:168)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:155)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:91)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:55)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
    ... 23 more

here is my persistence.xml file :

这是我的 persistence.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
    version="2.0">

    <persistence-unit name="licenta_pu"
        transaction-type="RESOURCE_LOCAL">
<!--        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <properties>
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/tulips"/>
            <property name="hibernate.connection.username" value="...." />
            <property name="hibernate.connection.password" value="...." />
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
            <property name="hibernate.show-sql" value="false" />
<!--            <property name="hibernate.jdbc.batch_size" value="1000" /> -->
            <!-- <property name="hibernate.hbm2ddl.auto" value="update" /> -->          
        </properties>
    </persistence-unit>
</persistence>

I've tried changing the hibernate provider but that didn't help :( [org.hibernate.ejb.HibernatePersistence and org.hibernate.jpa.HibernatePersistenceProvider]

我试过更改休眠提供程序,但这没有帮助:( [org.hibernate.ejb.HibernatePersistence 和 org.hibernate.jpa.HibernatePersistenceProvider]

I don't know exactly how to replicate this error, sometimes I get it, sometimes I don't. I have observed that every time after I restart my computer and run the project in Eclipse, and try to persist data, it works. If I stop the project, eventually add some data into the database via MySQL Workbench, and then run the project again, I get the error.

我不知道如何复制这个错误,有时我明白,有时我不明白。我观察到每次在我重新启动计算机并在 Eclipse 中运行项目并尝试保留数据后,它都可以工作。如果我停止该项目,最终通过 MySQL Workbench 将一些数据添加到数据库中,然后再次运行该项目,则会出现错误。

Here is my EntityManagerHolder:

这是我的 EntityManagerHolder:

public class EntityManagerHolder {

    private static EntityManagerHolder INSTANCE = new EntityManagerHolder();
    private EntityManagerFactory emf;
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public static EntityManagerHolder getInstance() {
        return INSTANCE;
    }

    private EntityManagerHolder() {
        super();
        emf = Persistence
                .createEntityManagerFactory("licenta_pu");
        entityManager = emf.createEntityManager();
    }

}

Here is my GenericDao:

这是我的 GenericDao:

import javax.persistence.EntityManager;
import javax.transaction.Transactional;

import com.tulips.model.AbstractEntity;

@Transactional
public abstract class GenericDao {

    protected EntityManager em;

    public GenericDao(EntityManager em) {
        this.em = em;
    }

    public void saveOrUpdate(AbstractEntity e) {
        if (e == null) {
            throw new NullPointerException("Trying to persist a null object");
        }
        em.getTransaction().begin();
        if (e.getId() == null) {
            em.persist(e);
        } else {
            em.merge(e);
        }
        em.getTransaction().commit();
    }


}

I'm using the following Hibernate libraries:

我正在使用以下 Hibernate 库:

        mysql-connector-java-5.1.9.jar;
        hibernate-commons-annotations-4.0.4.Final.jar;
        hibernate-core-4.3.4.Final.jar;
        hibernate-entitymanager-4.3.4.Final.jar;
        hibernate-jpa-2.1-api-1.0.0.Final.jar;

采纳答案by David Levesque

The problem might be that you have a single EntityManager shared by all Web requests. EntityManager is not thread safe. The standard approach in a webapp is to create a new instance of EntityManager for each request. It is ok to have a shared EntityManagerFactory, but not a shared EntityManager.

问题可能是您有一个由所有 Web 请求共享的 EntityManager。EntityManager 不是线程安全的。webapp 中的标准方法是为每个请求创建一个新的 EntityManager 实例。可以共享 EntityManagerFactory,但不能共享 EntityManager。

From the Hibernate doc:

休眠文档

An EntityManager is an inexpensive, non-threadsafe object that should be used once, for a single business process, a single unit of work, and then discarded. An EntityManager will not obtain a JDBC Connection (or a Datasource) unless it is needed, so you may safely open and close an EntityManager even if you are not sure that data access will be needed to serve a particular request.

EntityManager 是一个廉价的、非线程安全的对象,应该为单个业务流程、单个工作单元使用一次,然后丢弃。除非需要,否则 EntityManager 不会获得 JDBC 连接(或数据源),因此即使您不确定是否需要数据访问来服务特定请求,您也可以安全地打开和关闭 EntityManager。