Java EE 7 + 持久性 + Hibernate:无法持久化数据

Java EE 7 + Persistance + Hibernate: Unable to persist data

我是 Spring 引导开发人员,目前正在尝试使用 Java EE 7 和 JAX-RS 学习更轻量级的解决方案。我目前在尝试将数据从我的应用程序保存到我的数据库时遇到问题。感谢任何关于我做错的指示!

错误日志

25-Aug-2017 18:15:25.919 INFO [http-nio-8080-exec-32] org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation HHH000204: Processing PersistenceUnitInfo [
    name: jax-rs
    ...]
25-Aug-2017 18:15:26.025 INFO [http-nio-8080-exec-32] org.hibernate.Version.logVersion HHH000412: Hibernate Core {5.2.10.Final}
25-Aug-2017 18:15:26.027 INFO [http-nio-8080-exec-32] org.hibernate.cfg.Environment.<clinit> HHH000206: hibernate.properties not found
25-Aug-2017 18:15:26.083 INFO [http-nio-8080-exec-32] org.hibernate.annotations.common.reflection.java.JavaReflectionManager.<clinit> HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
25-Aug-2017 18:15:26.275 INFO [http-nio-8080-exec-32] org.hibernate.dialect.Dialect.<init> HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect
25-Aug-2017 18:15:26.861 INFO [http-nio-8080-exec-32] org.apache.openejb.assembler.classic.ReloadableEntityManagerFactory.createDelegate PersistenceUnit(name=jax-rs, provider=org.hibernate.jpa.HibernatePersistenceProvider) - provider time 976ms
Hibernate: 
    insert 
    into
        public.users
        (user_email, user_id) 
    values
        (?, ?)
25-Aug-2017 18:15:26.993 WARN [http-nio-8080-exec-32] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions SQL Error: -5501, SQLState: 42501
25-Aug-2017 18:15:26.994 ERROR [http-nio-8080-exec-32] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions user lacks privilege or object not found: USERS
25-Aug-2017 18:15:26.996 ERROR [http-nio-8080-exec-32] org.hibernate.internal.ExceptionMapperStandardImpl.mapManagedFlushFailure HHH000346: Error during managed flush [org.hibernate.exception.SQLGrammarException: could not prepare statement]
25-Aug-2017 18:15:26.996 WARNING [http-nio-8080-exec-32] org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion Unexpected exception from beforeCompletion; transaction will roll back
 javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1441)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3201)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2411)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.beforeCompletion(JtaTransactionCoordinatorImpl.java:320)
    at org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47)
    at org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:527)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:511)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforePrepare(TransactionImpl.java:413)
    at org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:262)
    at org.apache.geronimo.transaction.manager.TransactionManagerImpl.commit(TransactionManagerImpl.java:252)
    at org.apache.openejb.core.transaction.JtaTransactionPolicy.completeTransaction(JtaTransactionPolicy.java:331)
    at org.apache.openejb.core.transaction.TxRequired.commit(TxRequired.java:76)
    at org.apache.openejb.core.transaction.EjbTransactionUtil.afterInvoke(EjbTransactionUtil.java:77)
    at org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:255)
    at org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:203)
    at org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:265)
    at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:260)
    at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:89)
    at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:347)
    at io.adenix.service.UserService$$LocalBeanProxy.create(io/adenix/service/UserService.java)
    at io.adenix.controller.UserController.create(UserController.java:23)
    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:498)
    at org.apache.openejb.server.cxf.rs.PojoInvoker.performInvocation(PojoInvoker.java:43)
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
    at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:189)
    at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:99)
    at org.apache.openejb.server.cxf.rs.AutoJAXRSInvoker.invoke(AutoJAXRSInvoker.java:68)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor.run(ServiceInvokerInterceptor.java:59)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:252)
    at org.apache.openejb.server.cxf.rs.CxfRsHttpListener.doInvoke(CxfRsHttpListener.java:251)
    at org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:94)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.openejb.server.httpd.EEFilter.doFilter(EEFilter.java:65)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
    at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareStatement(StatementPreparerImpl.java:78)
    at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.buildBatchStatement(AbstractBatchImpl.java:136)
    at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.getBatchStatement(AbstractBatchImpl.java:125)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2984)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3503)
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:589)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1435)
    ... 66 more
Caused by: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: USERS
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)
    at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
    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:498)
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
    at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81)
    at com.sun.proxy.$Proxy111.prepareStatement(Unknown Source)
    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:498)
    at org.apache.openejb.resource.jdbc.managed.local.ManagedConnection.invokeUnderTransaction(ManagedConnection.java:237)
    at org.apache.openejb.resource.jdbc.managed.local.ManagedConnection.invoke(ManagedConnection.java:164)
    at com.sun.proxy.$Proxy175.prepareStatement(Unknown Source)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.doPrepare(StatementPreparerImpl.java:87)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
    ... 77 more
Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: USERS
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.SchemaManager.getTable(Unknown Source)
    at org.hsqldb.ParserDQL.readTableName(Unknown Source)
    at org.hsqldb.ParserDQL.readRangeVariableForDataChange(Unknown Source)
    at org.hsqldb.ParserDML.compileInsertStatement(Unknown Source)
    at org.hsqldb.ParserCommand.compilePart(Unknown Source)
    at org.hsqldb.ParserCommand.compileStatement(Unknown Source)
    at org.hsqldb.Session.compileStatement(Unknown Source)
    at org.hsqldb.StatementManager.compile(Unknown Source)
    at org.hsqldb.Session.execute(Unknown Source)
    ... 96 more

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>io.adenix</groupId>
  <artifactId>jax-rs</artifactId>
  <version>0.0.0-SNAPSHOT</version>

  <name>jax-rs</name>
  <packaging>war</packaging>

  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <hibernate.version>5.2.10.Final</hibernate.version>
  </properties>

  <build>
    <finalName>jax-rs</finalName>
  </build>

  <dependencies>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.16</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>${hibernate.version}</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>${hibernate.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>42.1.4</version>
    </dependency>
  </dependencies>
</project>

persistance.xml

<?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="jax-rs" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <class>io.adenix.entity.User</class>
    <properties>
      <property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/jax-rs"/>
      <property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
      <property name="hibernate.connection.username" value="user"/>
      <property name="hibernate.connection.password" value="password"/>
      <property name="hibernate.archive.autodetection" value="class"/>
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>
      <property name="hbm2ddl.auto" value="update"/>
      <property name="tomee.jpa.factory.lazy" value="true" />
    </properties>
  </persistence-unit>
</persistence>

JaxRSConfiguration.java

package io.adenix;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("api")
public class JaxRSConfiguration extends Application { }

UserController.java

package io.adenix.controller;

import io.adenix.service.UserService;

import javax.ejb.EJB;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;

@Path("users")
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
public class UserController {

  @EJB
  private UserService userService;

  @POST
  public void create(String email) {
    userService.create(email);
  }
}

UserService.java

package io.adenix.service;

import io.adenix.entity.User;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class UserService {

  @PersistenceContext
  private EntityManager em;

  public void create(String email) {
    em.persist(
      new User()
        .setEmail(email)
    );
  }
}

User.java

package io.adenix.entity;

import lombok.Setter;

import javax.persistence.*;
import javax.validation.constraints.NotNull;

@Entity
@Table(name = "users", schema = "public", catalog = "jax-rs")
public class User {

  @Id
  @Setter
  @Column(name = "user_id")
  private int id;

  @Basic
  @NotNull
  @Column(name = "user_email", nullable = false)
  private String email;

  public int getId() {
    return id;
  }

  public String getEmail() {
    return email;
  }

  public User setEmail(String email) {
    this.email = email;
    return this;
  }
}

更新 1

数据库

CREATE TABLE users
(
  user_id SERIAL NOT NULL CONSTRAINT users_pkey PRIMARY KEY,
  user_email VARCHAR(255) NOT NULL
);

更新 2

Docker命令复制我的数据库(手动制作table)

docker run --name jax-rs -e POSTGRES_PASSWORD=password -e POSTGRES_USER=user -e POSTGRES_DB=jax-rs -p 5432:5432 -d postgres

您输入了错误的 table 名称并将 names 放入 user class 而不是 user

@Table(name = "user", schema = "public", catalog = "jax-rs")

我发现我的问题是由于对 TomEE 在部署的应用程序中所扮演的角色缺乏了解造成的。

This answer 解决了我的问题(针对 Postgres 进行了调整)