Исключение пустых первичных ключей NamedNativeQuery JPA - PullRequest
0 голосов
/ 31 января 2020

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

@NamedNativeQueries({ @NamedNativeQuery(name = "Q_INSTRUMENTS", query = "SELECT i.ID, i.TICKER, i.ISIN, i.SEDOL, i.NAME, i.COUNTRY_ID, i.CONTRACT_SIZE, i.EXPIRY_DATE, i.TYPE_ID FROM INSTRUMENT i INNER JOIN COUNTRY c ON i.COUNTRY_ID = c.ID"
        + " GROUP BY i.ID, i.TICKER, i.ISIN, i.SEDOL, i.COUNTRY_ID, i.CONTRACT_SIZE, i.EXPIRY_DATE, i.TYPE_ID, c.NAME HAVING i.ID = MAX(i.ID) ORDER BY i.NAME, c.NAME ASC", resultClass = Instrument.class, resultSetMapping = "InstrumentMapping") })
@SqlResultSetMapping(name = "InstrumentMapping", entities = { @EntityResult(entityClass = Instrument.class, fields = {
        @FieldResult(name = "id", column = "ID"), @FieldResult(name = "ticker", column = "TICKER"),
        @FieldResult(name = "sedol", column = "SEDOL"), @FieldResult(name = "isin", column = "ISIN"),
        @FieldResult(name = "name", column = "NAME"), @FieldResult(name = "countryId", column = "COUNTRY_ID"),
        @FieldResult(name = "contractSize", column = "CONTRACT_SIZE"),
        @FieldResult(name = "expiryDate", column = "EXPIRY_DATE"), @FieldResult(name = "typeId", column = "TYPE_ID") }) })

, и вот класс, который аннотируется этим именованным запросом

public class Instrument extends ManagedEntityBase{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 10)
    private String ticker;

    @Column(length = 30)
    private String isin;

    @Column(length = 10, unique = true, nullable = false)
    private String sedol;

    @Column(length = 60, nullable = false)
    private String name;

    @Column(name = "COUNTRY_ID", nullable = false, insertable = false, updatable = false)
    private long countryId;

    @Column(name = "TYPE_ID", nullable = false, insertable = false, updatable = false)
    private byte typeId;

    @Column(name = "CONTRACT_SIZE", nullable = false)
    private Long contractSize;

    @Transient
    private String contractSizeString;

    @Temporal(TemporalType.DATE)
    @Column(name = "EXPIRY_DATE")
    private Date expiryDate;

    public Instrument() {
        // Default constructor
        this.contractSize = 1L;
    }

    ublic Instrument(String sedol, Country country, InstrumentType type) {
    this();
    this.sedol = sedol;
    this.country = country;
    this.type = type;
}

/**
 * Creates an {@link Instrument} with the given sedol, isin, country and type.
 * 
 * @param sedol instrument sedol
 * @param isin instrument isin
 * @param country instrument country
 * @param name
 * @param ticker
 * @param type instrument type
 */
public Instrument(String sedol, String isin, Country country, String name, String ticker, InstrumentType type) {
    this(sedol, country, type);
    this.isin = isin;
    this.name = name;
    this.ticker = ticker;
}

}

Когда я попытаться вызвать запрос имени:

public static List<Instrument> getInstruments() {
        return DatabaseUtility.getEntityManager().createNamedQuery("Q_INSTRUMENTS").getResultList();
    }

Я получаю следующую ошибку:

[EL Warning]: 2020-01-31 15:55:40.732--UnitOfWork(1788318093)--Exception [EclipseLink-6044] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.QueryException
Exception Description: The primary key read from the row [ArrayRecord(
     => 3000000002285
     => 00577
     => BMG8827A1045
     => BYX9N24
     => 13 HOLDINGS LTD, THE
     => 2
     => 1
     => null
     => 1)] during the execution of the query was detected to be null.  Primary keys must not contain null.
Query: ReadAllQuery(name="Q_INSTRUMENTS" referenceClass=Instrument sql="SELECT i.ID, i.TICKER, i.ISIN, i.SEDOL, i.NAME, i.COUNTRY_ID, i.CONTRACT_SIZE, i.EXPIRY_DATE, i.TYPE_ID FROM INSTRUMENT i INNER JOIN COUNTRY c ON i.COUNTRY_ID = c.ID GROUP BY i.ID, i.TICKER, i.ISIN, i.SEDOL, i.COUNTRY_ID, i.CONTRACT_SIZE, i.EXPIRY_DATE, i.TYPE_ID, c.NAME HAVING i.ID = MAX(i.ID) ORDER BY i.NAME, c.NAME ASC")

В таблице expiry_date действительно пусто, но это не принимает участие из первичного ключа и по умолчанию значение NULL в случае истечения срока действия истина. Я использую EclipseLink с Postre SQL. Я пытаюсь перенести текущий код из старой Sybase в новую Postre SQL. С источником данных Sybase ошибка не происходит.

Я пытался использовать

<property name="eclipselink.jpa.uppercase-column-names" value="true"/> 

, чтобы убедиться, что сопоставление столбцам не сделано неправильно, но это не устранило мою проблему

1 Ответ

1 голос
/ 04 февраля 2020

Кажется, мой вопрос содержал в себе ответ. Проблема была связана с неправильным отображением идентификатора. Сопоставление было выполнено с использованием «id», но столбец в базе данных - ID (с большой буквы). Вот почему у меня был ноль для идентификатора.

Решением было поместить

<property name="eclipselink.jpa.uppercase-column-names" value="true"/> 

в правильную единицу сопротивления.

...