Доступ к JPA Postgresql 9.4 сгенерировал идентификатор последовательности, не существует ошибки

У меня был проект, который должен был настроить SMS-шлюз, который работает с проектом JAVA-EE. Был выбран ГАММУ 1.36.0.

бэкэнд БД - это Postgresql 9.4, таблица "Входящие" и последовательность были созданы для хранения входящих SMS.

входящие, созданные с помощью:

CREATE TABLE inbox (
"UpdatedInDB" timestamp(0) WITHOUT time zone NOT NULL DEFAULT     LOCALTIMESTAMP(0),
"ReceivingDateTime" timestamp(0) WITHOUT time zone NOT NULL DEFAULT LOCALTIMESTAMP(0),
"Text" text NOT NULL,
"SenderNumber" varchar(20) NOT NULL DEFAULT '',
"Coding" varchar(255) NOT NULL DEFAULT 'Default_No_Compression',
"UDH" text NOT NULL,
"SMSCNumber" varchar(20) NOT NULL DEFAULT '',
"Class" integer NOT NULL DEFAULT '-1',
"TextDecoded" text NOT NULL DEFAULT '',
"ID" serial PRIMARY KEY,
"RecipientID" text NOT NULL,
"Processed" boolean NOT NULL DEFAULT 'false',
CHECK ("Coding" IN 
  ('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression')));

id - это порядковый номер, хранящийся в:

--CREATE SEQUENCE inbox_ID_seq;

структура таблицы выглядит так:

smsd-> \d inbox
                                            Table "public.inbox"
  Column       |              Type              |                           Modifiers                            
-------------------+--------------------------------+----------------------------------------------------------------
UpdatedInDB       | timestamp(0) without time zone | not null default ('now'::text)::timestamp(0) without time zone
ReceivingDateTime | timestamp(0) without time zone | not null default ('now'::text)::timestamp(0) without time zone
Text              | text                           | not null
SenderNumber      | character varying(20)          | not null default ''::character varying
Coding            | character varying(255)         | not null default 'Default_No_Compression'::character varying
UDH               | text                           | not null
SMSCNumber        | character varying(20)          | not null default ''::character varying
Class             | integer                        | not null default (-1)
TextDecoded       | text                           | not null default ''::text
ID                | integer                        | not null default nextval('"inbox_ID_seq"'::regclass)
RecipientID       | text                           | not null
Processed         | boolean                        | not null default false
Indexes:
"inbox_pkey" PRIMARY KEY, btree ("ID")
Check constraints:
"inbox_Coding_check" CHECK ("Coding"::text = ANY (ARRAY['Default_No_Compression'::character varying, 'Unicode_No_Compression'::character varying, '8bit'::character varying, 'Default_Compression'::character varying, 'Unicode_Compression'::character varying]::text[]))
Triggers:
update_timestamp BEFORE UPDATE ON inbox FOR EACH ROW EXECUTE PROCEDURE update_timestamp()

smsd-> 

Обратите внимание: позиция идентификаторов столбцов в таблице равна 10.

Эта таблица хорошо работает с GAMMU 1.36.0, правильно отправляет и получает SMS.

Когда я пытаюсь разработать EJB для переноса информации о входящих сообщениях в мое веб-приложение.

Я использую JPA 2.1, реализация EclipseLink 2.5.2. persistence.xml выглядит так:

<persistence-unit name="SmsdJPANBPU" transaction-type="RESOURCE_LOCAL">
       <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <mapping-file>com/longz/smsd/model/SmsdInboxEntity.xml</mapping-file>
    <mapping-file>com/longz/smsd/model/SmsdOutboxEntity.xml</mapping-file>
    <mapping-file>com/longz/smsd/model/SmsdSentitemsEntity.xml</mapping-file>
    <class>com.longz.smsd.model.SmsdInboxEntity</class>
    <class>com.longz.smsd.model.SmsdOutboxEntity</class>
    <class>com.longz.smsd.model.SmsdSentitemsEntity</class>
    <properties>
        <property name="eclipselink.jdbc.url" value="jdbc:postgresql://10.0.1.100:5433/smsd"/>
        <property name="eclipselink.jdbc.driver" value="org.postgresql.Driver"/>
        <property name="eclipselink.jdbc.user" value="any"/>
        <property name="eclipselink.jdbc.password" value="any"/>
        <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
    </properties>
</persistence-unit>

Объектный компонент JPA определен:

@Entity
@Table(name = "inbox", schema = "public", catalog = "smsd")
@NamedQueries({
    /*@NamedQuery(name = "Inbox.findAll", query = "SELECT i FROM InboxEntity i ORDER BY i.id DESC"),*/
    @NamedQuery(name = "Inbox.findAll", query = "SELECT i FROM SmsdInboxEntity i order by i.id desc"),
......
public class SmsdInboxEntity implements Serializable{
......
@Id
@SequenceGenerator(name="JOB_MISFIRE_ID_GENERATOR", sequenceName="inbox_ID_seq",schema = "public", allocationSize=1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="JOB_MISFIRE_ID_GENERATOR")
@Column(name = "ID", nullable = false, insertable = true, updatable = true)
public int getId() {
    return id;
}
......
}

сессионный компонент без сохранения состояния как:

@Remote(InboxEntityFacadeRemote.class)
@Stateless(mappedName= "inboxEntityFacadeEJB")
public class InboxEntityFacade extends AbstractFacade<SmsdInboxEntity> implements InboxEntityFacadeRemote {
@PersistenceContext(unitName = "SmsdJPANBPU")
private EntityManager em;

@Override
protected EntityManager getEntityManager() {
    return em;
}

public InboxEntityFacade() {
    super(SmsdInboxEntity.class);
}
@Override
public List<SmsdInboxEntity> findAll(){
    Query query = em.createNamedQuery("Inbox.findAll");
    return new LinkedList<SmsdInboxEntity>(query.getResultList());
    /*return super.findAll();*/
}

Я попытался использовать функцию findall() для отображения всех смс в папке «Входящие». Эта функция вызовет именованный оператор запроса:

@NamedQuery(name = "Inbox.findAll", query = "SELECT i FROM SmsdInboxEntity i order by i.id desc"),

Протестируйте клиент EJB как:

try {
        Context context = new InitialContext(properties);
        InboxEntityFacadeRemote inboxEnFaRemote = (InboxEntityFacadeRemote)context.lookup("inboxEntityFacadeEJB#com.longz.smsd.remote.InboxEntityFacadeRemote");
        System.out.println("inboxEntityFacadeEJB found.");
        List<com.longz.smsd.model.SmsdInboxEntity> todaysemails = inboxEnFaRemote.findAll();
        System.out.println("Records found: "+ todaysemails.size());
        todaysemails.stream().forEach((e) -> {
            System.out.println(e.getTextDecoded());
        });

    }catch (NamingException e) {
        e.printStackTrace();
    }

}

Пока все работает нормально. но очень странная ошибка:

run:
inboxEntityFacadeEJB found.
Exception in thread "main" javax.ejb.EJBException: EJB Exception: ; nested exception is: 
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: column "id" does not exist
  Position: 8
  Error Code: 0
Call: SELECT ID, Class, Coding, Processed, ReceivingDateTime, RecipientID, SenderNumber, SMSCNumber, Text, TextDecoded, UDH, UpdatedInDB FROM smsd.public.inbox ORDER BY ID DESC
Query: ReadAllQuery(name="Inbox.findAll" referenceClass=SmsdInboxEntity sql="SELECT ID, Class, Coding, Processed, ReceivingDateTime, RecipientID, SenderNumber, SMSCNumber, Text, TextDecoded, UDH, UpdatedInDB FROM smsd.public.inbox ORDER BY ID DESC")
at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.unwrapRemoteException(RemoteBusinessIntfProxy.java:117)
at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.invoke(RemoteBusinessIntfProxy.java:92)
at com.sun.proxy.$Proxy0.findAll(Unknown Source)
at weblogicejbclient.WeblogicInboxEJBClient.main(WeblogicInboxEJBClient.java:38)
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: column "id" does not exist
  Position: 8
  Error Code: 0
Call: SELECT ID, Class, Coding, Processed, ReceivingDateTime, RecipientID, SenderNumber, SMSCNumber, Text, TextDecoded, UDH, UpdatedInDB FROM smsd.public.inbox ORDER BY ID DESC
Query: ReadAllQuery(name="Inbox.findAll" referenceClass=SmsdInboxEntity sql="SELECT ID, Class, Coding, Processed, ReceivingDateTime, RecipientID, SenderNumber, SMSCNumber, Text, TextDecoded, UDH, UpdatedInDB FROM smsd.public.inbox ORDER BY ID DESC")
at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:378)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260)
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:469)
at com.longz.smsd.ejb.InboxEntityFacade.findAll(InboxEntityFacade.java:36)
at com.longz.smsd.ejb.InboxEntityFacadeEJB_s9wt3_InboxEntityFacadeRemoteImpl.__WL_invoke(Unknown Source)
at weblogic.ejb.container.internal.SessionRemoteMethodInvoker.invoke(SessionRemoteMethodInvoker.java:34)
at com.longz.smsd.ejb.InboxEntityFacadeEJB_s9wt3_InboxEntityFacadeRemoteImpl.findAll(Unknown Source)
at com.longz.smsd.ejb.InboxEntityFacadeEJB_s9wt3_InboxEntityFacadeRemoteImpl_WLSkel.invoke(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:701)
at weblogic.rmi.cluster.ClusterableServerRef.invoke(ClusterableServerRef.java:231)
at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:527)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:146)
at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:523)
at weblogic.rmi.internal.wls.WLSExecuteRequest.run(WLSExecuteRequest.java:118)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: column "id" does not exist
  Position: 8
  Error Code: 0
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:682)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2002)
at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:694)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2738)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRows(ExpressionQueryMechanism.java:2691)
at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:495)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1168)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127)
at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:403)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1215)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1751)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258)
... 15 more
Caused by: org.postgresql.util.PSQLException: ERROR: column "id" does not exist
  Position: 8
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:419)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:304)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1007)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:642)
... 35 more
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)

кажется, что PSQL пытается найти столбец «id» в позиции 8 вместо позиции 10, и на самом деле столбец «id» находится в позиции 10 в таблице «Входящие».

Любая идея и совет, пожалуйста! Оценил!!


person cidy.long    schedule 08.05.2015    source источник


Ответы (2)


Ваша проблема связана с регистрозависимостью: JPA работает в режиме без учета регистра по умолчанию (т. е. идентификаторы в запросах не заключаются в кавычки), а PostgreSQL преобразует все идентификаторы без кавычек в нижний регистр (так PostgreSQL пытается добиться независимости от регистра). Но вы определили свой столбец "ID" в режиме с учетом регистра (обратите внимание на кавычки).

Уродливый обходной путь заключается в том, что вы определяете свою сущность с учетом регистра:

@Column(name = "\"ID\"")

Или вы можете определить свою таблицу без учета регистра (что предпочтительнее):

CREATE TABLE inbox (
    ID serial PRIMARY KEY
    -- ...
);
person pozs    schedule 08.05.2015
comment
Большое спасибо! кажется, этот обходной путь работает для меня. К сожалению, я не могу переопределить схему БД, так как С++ должен ее использовать, он должен сохранить ее. Еще раз спасибо. - person cidy.long; 08.05.2015
comment
Спасибо за ваш ответ и совет. Я только что проверил это, но это не работает все время. - person cidy.long; 10.05.2015

В итоге. Эта проблема была устранена с помощью собственного SQL-запроса.

Query query = em.createNativeQuery("Select * from inbox",com.longz.smsd.model.SmsdInboxEntity.class);
return new LinkedList<SmsdInboxEntity>(query.getResultList());

Кажется, что JSQL не работает на 100% в этой ситуации.

Этот поможет кому-то еще, у кого такая же проблема.

person cidy.long    schedule 10.05.2015