org.postgresql.util.PSQLException: ОШИБКА: последовательность отношений не существует

Я создал динамический веб-проект с фасетом JPA, работающим на Tomcat 9.0.24. У меня есть одна таблица, называемая профилем, в моей базе данных Prostgres 10.10, и у меня есть один объект «Профиль», который я пытаюсь сохранить. Я использую Eclipse 4.12.0.

Таблица профилей была создана с помощью консоли pgAdmin 4, и ее последовательность существует.

Вот мой код...

Мейвен ПОМ:

<dependency>
  <groupId>org.eclipse.persistence</groupId>
  <artifactId>org.eclipse.persistence.jpa</artifactId>
  <version>2.7.4</version>
</dependency>

Сущность профиля:

package za.co.ezimax.entity;

import java.time.LocalDate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity()
@Table(name = "profile")
public class Profile {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name="first_name", nullable = false, length = 80)
    private String firstName;

    @Column(name="last_name", nullable = false, length = 80)
    private String lastName;

    @Column(name="birth_date", columnDefinition = "DATE",  nullable = false)
    private LocalDate birthDate;

    @Column(name="sex", nullable = false)
    private int sex;

    @Column(name="mobile_mac", nullable = false)
    private String mobileMac;

    @Column(name="mobile_no", nullable = false, length = 12)
    private String mobileNo;

    @Column(name="registration_date", columnDefinition = "DATE", nullable = false)
    private LocalDate registrationDate;

    @Column(name="user_password", nullable = false, length = 80)
    private char[] userPassword;

    public Profile() {
    }
}

Код для сохранения объекта:

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("ezimax");
        EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();

        Profile profile = new Profile();
        profile.setFirstName("Hendre");
        profile.setLastName("Louw");
        profile.setSex(1);
        profile.setMobileMac("ff:ff:ff:ff:ff:ff:ff:ff");
        profile.setMobileNo("+27832000000");
        profile.setRegistrationDate(LocalDate.now());
        profile.setUserPassword("password".toCharArray());

        em.persist(profile);
        em.getTransaction().commit();

        em.close();
        emf.close();

Вот исключение, которое я получаю:

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.4.v20190115-ad5b7c6b2a): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: relation "sequence" does not exist
  Position: 8
Error Code: 0
Call: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
    bind => [50, SEQ_GEN]
Query: DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?")
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:342)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1650)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:906)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:970)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:640)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:567)
    at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2096)
    at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:311)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:275)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:261)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:304)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:284)
    at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:87)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:914)
    at org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:3349)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1895)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1877)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1842)
    at org.eclipse.persistence.sequencing.QuerySequence.update(QuerySequence.java:356)
    at org.eclipse.persistence.sequencing.QuerySequence.updateAndSelectSequence(QuerySequence.java:293)
    at org.eclipse.persistence.sequencing.StandardSequence.getGeneratedVector(StandardSequence.java:75)
    at org.eclipse.persistence.sequencing.DefaultSequence.getGeneratedVector(DefaultSequence.java:168)
    at org.eclipse.persistence.sequencing.Sequence.getGeneratedVector(Sequence.java:267)
    at org.eclipse.persistence.internal.sequencing.SequencingManager$Preallocation_Transaction_NoAccessor_State.getNextValue(SequencingManager.java:487)
    at org.eclipse.persistence.internal.sequencing.SequencingManager.getNextValue(SequencingManager.java:1109)
    at org.eclipse.persistence.internal.sequencing.ClientSessionSequencing.getNextValue(ClientSessionSequencing.java:72)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:372)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:331)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.assignSequenceNumber(UnitOfWorkImpl.java:532)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNotRegisteredNewObjectForPersist(UnitOfWorkImpl.java:4388)
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.registerNotRegisteredNewObjectForPersist(RepeatableWriteUnitOfWork.java:523)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4333)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:596)
    at za.co.ezimax.rest.Servlet.doGet(Servlet.java:53)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.postgresql.util.PSQLException: ERROR: relation "sequence" does not exist
  Position: 8
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2468)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2211)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:309)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:446)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:370)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:149)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:124)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:898)
    ... 55 more


person Hendré    schedule 04.09.2019    source источник
comment
GenerationType.AUTO вообще не следует использовать   -  person Simon Martinelli    schedule 04.09.2019
comment
Конечно. Фактический тип зависит от базы данных, поэтому он не является переносимым и неясным, какая реализация используется.   -  person Kayaman    schedule 04.09.2019
comment
@SimonMartinelli Когда я изменяю GenerationType на SEQUENCE, исключение изменяется на Internal Exception: org.postgresql.util.PSQLException: ERROR: отношение seq_gen_sequence не существует   -  person Hendré    schedule 04.09.2019


Ответы (2)


Как вы упомянули, вы хотите использовать последовательности с JPA.

Поэтому вам нужно использовать GenerationType.SEQUENCE и настроить имя последовательности:

@Id
@GeneratedValue(
    strategy = GenerationType.SEQUENCE,
    generator = "sequence-generator"
)
@SequenceGenerator(
    name = "sequence-generator",
    sequenceName = "the_sequence_name"
)
private long id;

Замените the_sequence_name именем последовательности в PostgreSQL.

person Simon Martinelli    schedule 04.09.2019
comment
Мне также пришлось добавить allocationSize = 1 к @SequenceGenerator вот так @SequenceGenerator( name = "sequence-generator", sequenceName = "the_sequence_name", allocationSize = 1 ) - person FourtyTwo; 08.03.2020

В вашем случае GenerationType.AUTO переводится как GenerationType.TABLE. Код ожидает наличия таблицы с именем SEQUENCE, содержащей значения последовательностей. Поскольку его не существует, EclipseLink не может предоставить вам сгенерированные идентификаторы.

Либо создайте таблицу (и строку последовательности в ней), либо используйте другой файл GenerationType.

person Kayaman    schedule 04.09.2019
comment
Когда я изменяю GenerationType на SEQUENCE, тогда исключение изменяется на Internal Exception: org.postgresql.util.PSQLException: ERROR: отношение seq_gen_sequence не существует @Kayaman - person Hendré; 04.09.2019
comment
@Hendré, если вы хотите автогенерацию, загляните в документацию EclipseLink. Или вы можете создать последовательность самостоятельно. - person Kayaman; 04.09.2019
comment
Последовательность существует. Он был создан автоматически, когда я создал таблицу с помощью pgAdmin. - person Hendré; 04.09.2019
comment
@Hendré - это последовательность в той же схеме, что и таблица? Что такое stacktrace с последовательным подходом? - person Kayaman; 04.09.2019
comment
@Hendré Может быть, есть также триггер или значение по умолчанию, которое использует последовательность. Вид автоинкремента. Проверьте это, и если вы найдете такой триггер или значение по умолчанию, GenerationType будет IDENTITY - person Simon Martinelli; 04.09.2019
comment
@SimonMartinelli Нет значения по умолчанию и нет триггера. - person Hendré; 04.09.2019