JdbcTypeRecommendationException: не удалось определить рекомендуемый JdbcType для

Я обыскал весь Интернет, эти трюки не решили мою проблему. Вот моя сущность (упрощенная версия):

@Entity
@Table(name = "msg")
public class InternalMessage implements Serializable {
    private static final long serialVersionUID = 3768430013233258L;


    @PrePersist
    public void genTicketId() {
// something
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true)
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "internal_msg_parent_fk", nullable = true)
    private InternalMessage parent = null;

    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
        private List<InternalMessage> childMessages = new ArrayList<>();
}

Я не вижу никаких проблем, и до того, как я перешел на Spring boot 3 (спящий режим 6), все работало нормально.

Так в чем же может быть проблема?

Редактировать:

Mysql: 8.0.33
Spring boot: 3.3.3
Vscode 1.92.2
gradle: 8.10

Тот же результат: запустите приложение в режиме отладки в vscode или командной строке: ./gradlew bootRun

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

public Predicate toPredicate(Root<InternalMessage> root, CriteriaQuery<?> query,
                CriteriaBuilder criteriaBuilder) {
            List<Predicate> predicates = new ArrayList<>();

            if (search == null || search.trim().isEmpty()) {
  // this part is causing me issue
                Expression<InternalMessage> parent = root.get("parent").as(InternalMessage.class);
                Predicate p = criteriaBuilder.isNull(parent);
                predicates.add(p);
                query.distinct(true);
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            } else {
// this part works
            }

        }

и это строка, вызывающая исключение:

                Expression<InternalMessage> parent = root.get("parent").as(InternalMessage.class);

Что-то не так с приведенной выше строкой? Это работало в более старой весенней загрузке/спящем режиме.

Можете ли вы подробно указать, какую версию весенней загрузки вы используете. Предоставьте файл конфигурации maven/gradle. Также укажите, какую базу данных вы используете? Я попробовал ваш код с весенней загрузкой 3.3.2 и базой данных h2, ошибок не обнаружено.

Dhaval Gajjar 26.08.2024 20:52

Спасибо Дхавал, только что обновил пост подробными версиями.

The MW 26.08.2024 21:42

Можете ли вы также предоставить еще несколько строк трассировки стека исключений, пожалуйста?

Francesco Poli 26.08.2024 21:43

@FrancescoPoli добавил. Но пришлось удалить зависимости.

The MW 26.08.2024 21:54

ок, удалил нижнюю часть трассировки стека и добавил зависимости.

The MW 26.08.2024 22:04

ОК, добавлено больше информации

The MW 26.08.2024 22:18

Я заметил это только после вашего последнего обновления: столбец соединения (где, как я полагаю, сохраняется идентификатор родительского элемента) называется «родительским», а атрибут InternalMessage также называется «родительским»? Может ли это псевдонимирование привести к тому, что Hibernate неправильно оценит то, что управляет, а затем попытается неправильно обработать родительский экземпляр? Действительно, в данном случае это вина Hibernate...

Francesco Poli 27.08.2024 10:25

Просто ради любопытства... пробовали ли вы установить @JoinColumn(name = "PARENT", nullable = true) (обратите внимание на верхний регистр имени столбца)?

Francesco Poli 27.08.2024 10:37

Спасибо @FrancescoPoli, это не так, для простоты я использовал «родительский», но имя столбца на самом деле другое: internal_msg_parent_fk. Сейчас обновляю пост.

The MW 27.08.2024 13:01

Почему вы моделируете свою сущность двунаправленной? Есть ли вариант использования, который нельзя охватить путем моделирования сверху вниз (только удержание дочерних сообщений) (родительский элемент все равно может быть частью таблицы!).

Valerij Dobler 28.08.2024 00:03

@ValerijDobler Изначально у меня был только parent, у меня нет List..., и он отлично работал при весенней загрузке 2.6.4 (которая была версией до миграции). Я добавил вторую часть только из-за исключения, с которым столкнулся сейчас (и в некоторых сообщениях говорится, что это может решить проблему, но это не так)

The MW 28.08.2024 01:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
1
11
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Мне удалось воспроизвести вашу ошибку локально. Я создал реализацию интерфейса Specification, чтобы иметь почти одинаковый метод toPredicate и использование контекста. Подтверждаю также, что ошибка происходит из строки:

Expression<InternalMessage> parent = root.get("parent").as(InternalMessage.class);

В любом случае мне удалось решить проблему заменой строк:

Expression<InternalMessage> parent = root.get("parent").as(InternalMessage.class);
Predicate p = criteriaBuilder.isNull(parent);

С помощью этого единственного утверждения удаляем промежуточный шаг Expression:

Predicate p = criteriaBuilder.isNull(root.get("parent"));

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

select distinct im1_0.id,im1_0.internal_msg_parent_fk from msg im1_0 where im1_0.internal_msg_parent_fk is null

Кажется, это то, что требуется в оригинальном методе toPredicate. Позвольте мне посмотреть, решит ли это проблему в вашем приложении.

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

Expression<Long> parent = root.get("parent").as(Long.class);

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

select distinct im1_0.id,im1_0.internal_msg_parent_fk from msg im1_0 where cast(im1_0.internal_msg_parent_fk as bigint) is null

где есть это приведение (... как bigint), которое в данном случае совершенно ненужно.

Спасибо @Франческо!!! Это действительно решило проблему. Оба предложения работают! Да, первый проще и лучше. Я думаю, это может быть связано с этой проблемой: stackoverflow.com/questions/78913982 и stackoverflow.com/a/76522587/14072498 Большое спасибо!!!

The MW 28.08.2024 01:03

Да, действительно. Возможно, это те же побочные эффекты, что и у других вопросов: stackoverflow.com/questions/78844558 и stackoverflow.com/questions/77648311, какой беспорядок...

Francesco Poli 28.08.2024 11:25

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