Собственный именованный запрос завершается ошибкой с исключением: «столбец имеет дату типа, но выражение имеет тип bytea», если в качестве входных данных задано значение NULL LocalDate - PullRequest
0 голосов
/ 31 августа 2018

Запрос:

    INSERT INTO PERSON 
        (email, mobile, party_id, affiliate_id, eligibility, member_start_date, created_by, created_dt, first_name, last_name, google_connected) 
        values 
        ('xxx@yyy.org', NULL, 123, '123', '1', NULL, NULL, '2018-8-30 21:45:56.859000 -6:0:0', 'xxx', 'yyy', '0')
        ON CONFLICT (email) 
        DO UPDATE SET create_dt = '2018-8-30 21:45:56.859000 -6:0:0' where email = ?

Когда значение LocalDate не равно нулю, оно работает нормально. Столкнувшись с этой проблемой, только когда значение LocalDate задано как ноль.

Даже после приведения PostgreSQL он делает то же самое.

Трассировка стека исключений:

2018-08-30 21: 10: 48,372 - [ОШИБКА] - Возникла непредвиденная проблема с вашим запросом org.postgresql.util.PSQLException: ОШИБКА: столбец "member_start_date" имеет тип date, но выражение имеет тип bytea
Подсказка: вам нужно будет переписать или привести выражение. Позиция: 185 в org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse (QueryExecutorImpl.java:2182) в org.postgresql.core.v3.QueryExecutorImpl.processResults (QueryExecutorImpl.java:1911) в org.postgresql.core.v3.QueryExecutorImpl.execute (QueryExecutorImpl.java:173) в org.postgresql.jdbc2.AbstractJdbc2Statement.execute (AbstractJdbc2Statement.java:645) в org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags (AbstractJdbc2Statement.java:495) в org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery (AbstractJdbc2Statement.java:380) в sun.reflect.GeneratedMethodAccessor98.invoke (неизвестный источник) в sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) в java.lang.reflect.Method.invoke (Method.java:498) в org.apache.tomcat.jdbc.pool.StatementFacade $ StatementProxy.invoke (StatementFacade.java:114) на com.sun.proxy. $ Proxy185.executeQuery (Неизвестный источник) на at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract (ResultSetReturnImpl.java:70) ... пропущено 149 общих кадров

Организация:

@Entity(name = "person")
@EqualsAndHashCode(callSuper = false)
public class PersonEntity extends Audit {

@Id
@GeneratedValue
@Column(name = "person_id", columnDefinition = "uuid", updatable = false)
private UUID id;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

@Column(name = "email")
@NotNull
private String email;

@Column(name = "mobile")
private String mobile;

@Column(name = "party_id")
private Long partyId;

@Column(name = "affiliate_id")
private String affiliateId;

@Column(name = "eligibility")
@NotNull
private Boolean eligibility;

@Column(name = "member_start_date")
private LocalDate memberStartDate;

@Column(name = "google_connected")
private Boolean googleAccountConnected;
}

определение таблицы PostgreSQL; отсутствует столбец google_connected, что не важно:

CREATE TABLE person
( 
   person_id             UUID NOT NULL,
   email                 VARCHAR(128) NOT NULL,
   mobile                VARCHAR(20), 
   party_id              INTEGER,
   affiliate_id          VARCHAR(20),
   eligibility              BOOLEAN NOT NULL,
   member_start_date     DATE, 
   created_by            VARCHAR(128) NOT NULL,
   created_dt            TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
   updated_by            VARCHAR(128) DEFAULT NULL,
   updated_dt            TIMESTAMP NULL,
   CONSTRAINT person_pk PRIMARY KEY ( person_id )
 );

1 Ответ

0 голосов
/ 31 августа 2018

Поскольку запрос является нативным, Hibernate не знает ожидаемых типов данных, поэтому при передаче значения NULL по умолчанию используется универсальный обработчик типов Serializable. Изменение этого поведения нарушает совместимость с другими базами данных.

Postgres, однако, немедленно анализирует запрос и определяет, какие типы являются приемлемыми, и всегда проверяет тип, прежде чем проверяет нулевое значение. Они единственные, кто может это исправить, но отказывается это сделать и говорит, что это работает как задумано.

Единственные решения для вас:

  • использовать JPQL
  • использовать управляемые объекты
  • использовать жестко запрограммированные нули в строке запроса, где вам нужно

К счастью для третьего варианта, в Hibernate вы можете использовать именованные параметры в собственных запросах, поэтому вам не нужно выполнять позиционные вычисления, когда что-то доступно, а когда нет.

edit: 4-е решение, которое я обнаружил с тех пор.

У вас есть запрос:

Query q = em.createNativeQuery("UPDATE...");

Где-нибудь есть статический конечный объект LocalDate:

public static final LocalDate EPOCH_DATE = LocalDate.of(1970, 1, 1);

затем вызовите запрос следующим образом:

q.setParameter("start_date", EPOCH_DATE);
q.setParameter("start_date", nullableDateParam);

При первом вызове setParameter для параметра Hibernate использует класс для разрешения типа. Во второй раз, когда вы вызываете его, тип уже разрешен, поэтому будет работать ноль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...