Почему JPA все еще работает с классом записи как с сущностью?

Судя по всей прочитанной мною документации, следующий код не должен работать; записи Java неизменяемы и не будут работать с JPA. Однако следующий код работает. Я могу успешно получить данные из базы данных. Может ли JPA поддерживать записи Java в сценариях только для чтения?

@Embeddable
public record TaxableLimitAmountId(@Column(name = "TAX_YR") String taxYr,
        @Column(name = "TAXL_LMT_UID") int taxableLimitUniqueId,
        @Column(name = "EFF_STDT", columnDefinition = "DATE") Date effectiveStartDate)
        implements Serializable {

    private static final long serialVersionUID = 1L;

}

@Entity
@Table(name = "TableName", schema = "schema")
public record TaxableLimitAmountEntity(
        @EmbeddedId TaxableLimitAmountId taxableLimitAmountId,
        @Column(name = "TAXL_LMT_AMT", columnDefinition = "DECIMAL") BigDecimal taxableLimitAmount,
        @Column(name = "EFF_ENDT", columnDefinition = "DATE") Date effectiveEndDate,
        @Column(name = "INSRT_TS") Timestamp insertTimeStamp,
        @Column(name = "LU_TS") Timestamp updateTimeStamp) {

}

public record FicaMaxData(int taxYr, BigDecimal taxableLimitAmount) {

}

@Repository
public interface TaxableLimitAmountRepo
        extends JpaRepository<TaxableLimitAmountEntity, Integer> {

    @Query("SELECT NEW gov.ssa.irsrptg.repo.FicaMaxData(CAST(tla.taxableLimitAmountId.taxYr as INTEGER),tla.taxableLimitAmount) FROM TaxableLimitAmountEntity tla "
            + "WHERE tla.taxableLimitAmountId.taxableLimitUniqueId = 1")
    List<FicaMaxData> getFicaMaxAllYears();

    @Query("SELECT tla.taxableLimitAmount FROM TaxableLimitAmountEntity tla "
            + "WHERE tla.taxableLimitAmountId.taxableLimitUniqueId = 1 and tla.taxableLimitAmountId.taxYr = :taxYr")
    BigDecimal getFicaMaxSpecificYear(@Param("taxYr") String taxYr);
}


Hibernate выдает следующее предупреждение, но не выдает никаких ошибок

o.h.m.i.EntityInstantiatorPojoStandard   : HHH000182: No default (no-argument) constructor for class: gov.ssa.irsrptg.repo.TaxableLimitAmountEntity (class must be instantiated by Interceptor)

Я использую Java 17, Spring Boot 3.2.6, Spring Data Jpa 3.2.6 и Hibernate 6.4.8.Final.

Однако это своего рода обман: вы делаете select new, который не является «обычным» JPA, это «обход проблем с соглашениями» JPA. Интересно, сработает ли это, если делать регулярно select bla from TaxableLimitAmountEntity bla. Возможно, записи — это, по сути, синтаксический сахар. Но без официальной поддержки я бы не рискнул.

Gimby 28.08.2024 16:40
getFicaMaxAllYears() даже не создает экземпляры TaxableLimitAmountEntity, а только использует метаинформацию для создания SQL-запроса и сопоставления с конструктором FicaMaxData. Кроме того, Hibernate должен иметь возможность создавать экземпляр записи посредством отражения (как сказал Гимби, записи представляют собой более синтаксический сахар, хотя отражение также накладывает некоторые ограничения на записи) и, таким образом, иметь возможность загружать эти экземпляры - возможно, они даже будут отсоединены по мере изменений. от них этого не ожидалось.
Thomas 28.08.2024 17:10

Выбор @Gimby без нового приводит к поломке кода.

solutionsDeveloper 28.08.2024 17:19

JPA не требует создания исключений для записей: все, что не указано, просто не поддерживается — используйте на свой страх и риск. То, что его можно прочитать из базы данных и созданных экземпляров, связано с деталями реализации конкретных поставщиков JPA, но не будет единообразным. Запись или изменения в БД могут привести к сбою, поскольку JPA требует сохранения идентичности объекта, что означает обновление значений для кэшированных объектов при наличии изменений.

Chris 29.08.2024 15:00
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Утверждение «JPA не работает с записями для сущностей» представляет собой короткую форму: «Есть вещи, которые JPA требует от сущности, что невозможно с записями».

Жестким ограничением здесь является неизменяемость, которая не позволяет JPA работать должным образом, отслеживая изменения в объекте.

Конечно, это не означает, что реализация JPA должна немедленно взорваться вам в лицо, если она обнаружит запись. Некоторые вещи могут работать нормально, потому что эти функции не нужны для данного варианта использования. Например, вам не нужен конструктор по умолчанию, когда вы используете выражение конструктора. Или ваша реализация JPA может обойти некоторые ограничения JPA, как это делает Hibernate из-за отсутствия конструктора по умолчанию, на что намекает

Нет конструктора по умолчанию (без аргументов) для класса: gov.ssa.irsrptg.repo.TaxableLimitAmountEntity (экземпляр класса должен быть создан Interceptor)

Так что да: некоторые вещи могут сработать.

До сих пор я не видел официального заявления JPA или Hibernate о том, какие именно вещи работают, и я бы не хотел полагаться на функции, которые просто работают, поскольку они могут перестать работать в следующем выпуске.

Другие вопросы по теме

Похожие вопросы

Приложение Spring Framework возвращает только ошибки 404
Spring: получение ошибки грамматики неправильного sql для именованного параметра – удаление параметра устраняет ошибку
Есть ли в Visual Studio Code сочетания клавиш, которые переключают детали предложения и всплывающие окна режима объяснения в предложениях?
Вывод консоли IntelliJ IDEA неправильно отображает символы вертикальной табуляции (U + 000B)
Ошибка создания bean-компонента с именем «entityManagerFactory», определенным в ресурсе пути к классу: невозможно построить Hibernate SessionFactory;
Как использовать внешние файлы конфигурации для обеспечения специфичных для среды конфигураций в приложении Spring Boot?
Как использовать общие файлы миграции для mysql и h2
Отключение клиента администратора Kafka Streams
Укажите дополнительную версию Java в maven-compiler-plugin
Класс регистратора Log4j2 с двумя отдельными файлами журнала